当前位置:网站首页>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
}
边栏推荐
- Redis之Bitmap
- CSP first week of question brushing
- 在QWidget上实现窗口阻塞
- BN折叠及其量化
- LeetCode:673. Number of longest increasing subsequences
- Simclr: comparative learning in NLP
- Cesium draw points, lines, and faces
- [OC]-<UI入门>--常用控件的学习
- [today in history] February 13: the father of transistors was born The 20th anniversary of net; Agile software development manifesto was born
- Advanced Computer Network Review(3)——BBR
猜你喜欢
Selenium+Pytest自动化测试框架实战
Redis之Bitmap
[three storage methods of graph] just use adjacency matrix to go out
Selenium+pytest automated test framework practice
Intel Distiller工具包-量化实现2
自定义卷积注意力算子的CUDA实现
【图的三大存储方式】只会用邻接矩阵就out了
Nacos installation and service registration
一篇文章带你了解-selenium工作原理详解
[OC]-<UI入门>--常用控件-UIButton
随机推荐
Five layer network architecture
Detailed explanation of dynamic planning
I-BERT
Ijcai2022 collection of papers (continuously updated)
CSP salary calculation
I-BERT
Intel Distiller工具包-量化实现2
【shell脚本】使用菜单命令构建在集群内创建文件夹的脚本
[oc]- < getting started with UI> -- common controls - prompt dialog box and wait for the prompt (circle)
[today in history] February 13: the father of transistors was born The 20th anniversary of net; Agile software development manifesto was born
Mathematical modeling 2004b question (transmission problem)
What is MySQL? What is the learning path of MySQL
Pytest参数化你不知道的一些使用技巧 /你不知道的pytest
SimCLR:NLP中的对比学习
Intel distiller Toolkit - Quantitative implementation 3
[oc foundation framework] - < copy object copy >
【每日一题】搬运工 (DFS / DP)
SAP ui5 date type sap ui. model. type. Analysis of the parsing format of date
力扣每日一题(二)
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