当前位置:网站首页>Kratos战神微服务框架(三)
Kratos战神微服务框架(三)
2022-07-06 08:59:00 【~庞贝】
Kratos战神微服务框架(三)
中间件
package auth
import (
"context"
"errors"
"fmt"
"github.com/davecgh/go-spew/spew"
"github.com/golang-jwt/jwt/v4"
"strings"
"time"
"github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/transport"
)
func GenerateToken(secret, username string) string {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": username,
"nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),
})
// Sign and get the complete encoded token as a string using the secret
tokenString, err := token.SignedString([]byte(secret))
if err != nil {
panic(err)
}
fmt.Println(tokenString, err)
return tokenString
}
func JWTAuth(secret string) middleware.Middleware {
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{
}) (reply interface{
}, err error) {
if tr, ok := transport.FromServerContext(ctx); ok {
tokenString := tr.RequestHeader().Get("Authorization")
auths := strings.SplitN(tokenString, " ", 2)
if len(auths) != 2 || !strings.EqualFold(auths[0], "Token") {
return nil, errors.New("jwt token missing")
}
token, err := jwt.Parse(auths[1], func(token *jwt.Token) (interface{
}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("err %v", token)
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
spew.Dump(claims["username"])
} else {
return nil, errors.New("Token Invalid")
}
}
return handler(ctx, req)
}
}
}
func NewHTTPServer(c *conf.Server, jwtc *conf.JWT, greeter *service.RealWorldService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.ErrorEncoder(errorEncoder),
http.Middleware(
recovery.Recovery(),
selector.Server(auth.JWTAuth(jwtc.Token)).Match(NewSkipRoutersMatcher()).Build(), //添加选择器过滤
//auth.JWTAuth(jwtc.Token),
),
http.Filter(handlers.CORS( // 解决跨域问题
handlers.AllowedHeaders([]string{
"X-Requested-With", "Content-Type", "Authorization"}),
handlers.AllowedMethods([]string{
"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
handlers.AllowedOrigins([]string{
"*"}),
)),
}
if c.Http.Network != "" {
opts = append(opts, http.Network(c.Http.Network))
}
if c.Http.Addr != "" {
opts = append(opts, http.Address(c.Http.Addr))
}
if c.Http.Timeout != nil {
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
}
srv := http.NewServer(opts...)
v1.RegisterRealWorldHTTPServer(srv, greeter)
return srv
}
实现中间件过滤
func NewSkipRoutersMatcher() selector.MatchFunc {
skipRouters := make(map[string]struct{
})
skipRouters["/realworld.v1.RealWorld/Login"] = struct{
}{
} // jwt过滤login和register
skipRouters["/realworld.v1.RealWorld/Register"] = struct{
}{
}
return func(ctx context.Context, operation string) bool {
if _, ok := skipRouters[operation]; ok {
return false
}
return true
}
}
解决跨域问题
http.Filter(handlers.CORS(
handlers.AllowedHeaders([]string{
"X-Requested-With", "Content-Type", "Authorization"}),
handlers.AllowedMethods([]string{
"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
handlers.AllowedOrigins([]string{
"*"}),
)),
// NewHTTPServer new a HTTP server.
func NewHTTPServer(c *conf.Server, jwtc *conf.JWT, greeter *service.RealWorldService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.ErrorEncoder(errorEncoder),
http.Middleware(
recovery.Recovery(),
selector.Server(auth.JWTAuth(jwtc.Token)).Match(NewSkipRoutersMatcher()).Build(),
//auth.JWTAuth(jwtc.Token),
),
http.Filter(handlers.CORS( // 解决跨域
handlers.AllowedHeaders([]string{
"X-Requested-With", "Content-Type", "Authorization"}),
handlers.AllowedMethods([]string{
"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
handlers.AllowedOrigins([]string{
"*"}),
)),
}
if c.Http.Network != "" {
opts = append(opts, http.Network(c.Http.Network))
}
if c.Http.Addr != "" {
opts = append(opts, http.Address(c.Http.Addr))
}
if c.Http.Timeout != nil {
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
}
srv := http.NewServer(opts...)
v1.RegisterRealWorldHTTPServer(srv, greeter)
return srv
}
自定义错误
package errors
import (
"errors"
"fmt"
)
type HTTPError struct {
Errors map[string][]string `json:"errors"`
Code int `json:"-"`
}
func NewHTTPError(code int, field string, detail string) *HTTPError {
return &HTTPError{
Code: code, Errors: map[string][]string{
field: {
detail},
}}
}
func (e *HTTPError) Error() string {
return fmt.Sprintf("HTTPError %d", e.Code)
}
func FromError(err error) *HTTPError {
if err == nil {
return nil
}
if se := new(HTTPError); errors.As(err, &se) {
return se
}
return &HTTPError{
}
}
package server
import (
"github.com/go-kratos/kratos/v2/transport/http"
e "helloworld/internal/errors"
stdhttp "net/http"
)
func errorEncoder(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) {
se := e.FromError(err)
codec, _ := http.CodecForRequest(r, "Accept")
body, err := codec.Marshal(se)
if err != nil {
w.WriteHeader(500)
return
}
w.Header().Set("Content-Type", "application/"+codec.Name())
w.WriteHeader(se.Code)
_, _ = w.Write(body)
}
使用:
func (s *RealWorldService) Login(ctx context.Context, req *v1.LoginRequest) (*v1.UserReply, error) {
if len(req.User.Email) == 0 {
return nil, errors.NewHTTPError(422, "email", "can't be empty")
}
return &v1.UserReply{
User: &v1.UserReply_User{
Username: "jjj",
},
}, nil
}
边栏推荐
- What is an R-value reference and what is the difference between it and an l-value?
- Leetcode: Sword finger offer 42 Maximum sum of continuous subarrays
- The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
- Selenium+pytest automated test framework practice
- KDD 2022论文合集(持续更新中)
- An article takes you to understand the working principle of selenium in detail
- LeetCode:221. 最大正方形
- LeetCode:39. Combined sum
- UML图记忆技巧
- Leetcode刷题题解2.1.1
猜你喜欢

CUDA实现focal_loss

Redis之性能指标、监控方式

Problems encountered in connecting the database of the project and their solutions

Mise en œuvre de la quantification post - formation du bminf

Advanced Computer Network Review(4)——Congestion Control of MPTCP

Intel distiller Toolkit - Quantitative implementation 2

多元聚类分析

项目连接数据库遇到的问题及解决

Intel distiller Toolkit - Quantitative implementation 3

【剑指offer】序列化二叉树
随机推荐
LeetCode:394. String decoding
Intel Distiller工具包-量化实现1
LeetCode:498. Diagonal traversal
Selenium+pytest automated test framework practice (Part 2)
[MySQL] limit implements paging
LeetCode:836. 矩形重叠
Nacos 的安装与服务的注册
Digital people anchor 618 sign language with goods, convenient for 27.8 million people with hearing impairment
Chapter 1 :Application of Artificial intelligence in Drug Design:Opportunity and Challenges
[three storage methods of graph] just use adjacency matrix to go out
【图的三大存储方式】只会用邻接矩阵就out了
Advanced Computer Network Review(3)——BBR
Leetcode: Sword finger offer 42 Maximum sum of continuous subarrays
UML图记忆技巧
【shell脚本】——归档文件脚本
LeetCode:124. Maximum path sum in binary tree
LeetCode:221. Largest Square
Notes 01
Super efficient! The secret of swagger Yapi
Computer graduation design PHP Zhiduo online learning platform