当前位置:网站首页>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
}
边栏推荐
- Tdengine biweekly selection of community issues | phase III
- [OC foundation framework] - [set array]
- Leetcode: Jianzhi offer 04 Search in two-dimensional array
- KDD 2022 paper collection (under continuous update)
- LeetCode:39. Combined sum
- Mise en œuvre de la quantification post - formation du bminf
- Intel distiller Toolkit - Quantitative implementation 1
- [OC-Foundation框架]-<字符串And日期与时间>
- Five layer network architecture
- 【shell脚本】使用菜单命令构建在集群内创建文件夹的脚本
猜你喜欢

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

甘肃旅游产品预订增四倍:“绿马”走红,甘肃博物馆周边民宿一房难求

LeetCode:236. 二叉树的最近公共祖先

Digital people anchor 618 sign language with goods, convenient for 27.8 million people with hearing impairment

In depth analysis and encapsulation call of requests

IJCAI2022论文合集(持续更新中)

【剑指offer】序列化二叉树
![[three storage methods of graph] just use adjacency matrix to go out](/img/79/337ee452d12ad477e6b7cb6b359027.png)
[three storage methods of graph] just use adjacency matrix to go out

Different data-driven code executes the same test scenario

Cesium draw points, lines, and faces
随机推荐
Five layer network architecture
Intel Distiller工具包-量化实现1
[daily question] Porter (DFS / DP)
Compétences en mémoire des graphiques UML
[OC-Foundation框架]--<Copy对象复制>
[three storage methods of graph] just use adjacency matrix to go out
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
Alibaba cloud server mining virus solution (practiced)
LeetCode:673. Number of longest increasing subsequences
[oc]- < getting started with UI> -- common controls - prompt dialog box and wait for the prompt (circle)
Super efficient! The secret of swagger Yapi
AcWing 2456. Notepad
SAP ui5 date type sap ui. model. type. Analysis of the parsing format of date
LeetCode:221. 最大正方形
Li Kou daily question 1 (2)
七层网络体系结构
Opencv+dlib realizes "matching" glasses for Mona Lisa
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
An article takes you to understand the working principle of selenium in detail
自定义卷积注意力算子的CUDA实现