From 98f2f11cce6eef00d629ac88d5a0ec42c87b1aff Mon Sep 17 00:00:00 2001 From: pyihe <785131182@qq.com> Date: Tue, 30 Aug 2022 18:01:42 +0800 Subject: [PATCH] add jwt --- go.mod | 1 + go.sum | 2 ++ https/http_api/cmd/main.go | 72 ++++++++++++++++++++++++++++++++++++-- https/http_api/http.go | 48 ++++++++++++++++++++++++- 4 files changed, 120 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d5dca90..929070c 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/go-openapi/swag v0.22.1 // indirect github.com/go-playground/validator/v10 v10.11.0 // indirect github.com/goccy/go-json v0.9.10 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect diff --git a/go.sum b/go.sum index bbcbfad..35a3d0e 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.10 h1:hCeNmprSNLB8B8vQKWl6DpuH0t60oEs+TAk9a7CScKc= github.com/goccy/go-json v0.9.10/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= diff --git a/https/http_api/cmd/main.go b/https/http_api/cmd/main.go index 61a8db1..c35a97b 100644 --- a/https/http_api/cmd/main.go +++ b/https/http_api/cmd/main.go @@ -1,16 +1,79 @@ package main import ( + "time" + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" "github.com/pyihe/go-pkg/https/http_api" "github.com/pyihe/go-pkg/tools" ) +const ( + publicKey = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuXws30YUeNhHeEqaxvCF +sQy8OrnFpj7nQ36vBVp6W3jid0QhBIOGDJicKPvpNsYiil/a/N2bn2oFpEGWW2UL +9NK5GSlxsJR1lUX+pHCvMqAuUMtkbAUFN+5x81yD5s4IlKeB4o4+5gTPbykTd1Xr +bWElHKci9o/qeLWqefVtahULs8V8lPDXu9aHQRZxhFnK49hFj1NnjjGkRRxqIwVB +B8En6lcbkfbeMvoucLtVjjPJmQeqTBbhUPSb3Bq7XFwS8CalpTGMNq+/8etDfNvr +Mx3fsR7Xl0eLeRZwHzmDSD/e8isU8o09MYJyuf12Gn+Vk57+CGp8wCSbcEBgxIVw +YwIDAQAB +-----END PUBLIC KEY----- +` + + privateKey = `-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5fCzfRhR42Ed4 +SprG8IWxDLw6ucWmPudDfq8FWnpbeOJ3RCEEg4YMmJwo++k2xiKKX9r83ZufagWk +QZZbZQv00rkZKXGwlHWVRf6kcK8yoC5Qy2RsBQU37nHzXIPmzgiUp4Hijj7mBM9v +KRN3VettYSUcpyL2j+p4tap59W1qFQuzxXyU8Ne71odBFnGEWcrj2EWPU2eOMaRF +HGojBUEHwSfqVxuR9t4y+i5wu1WOM8mZB6pMFuFQ9JvcGrtcXBLwJqWlMYw2r7/x +60N82+szHd+xHteXR4t5FnAfOYNIP97yKxTyjT0xgnK5/XYaf5WTnv4IanzAJJtw +QGDEhXBjAgMBAAECggEAXUAkfwuId0ikhcFcFvANBnnUl+GVkILHWZNzAkn+gcZA +dJ13zAEjf2mp+KDNGpB6BP8z5TS0bGys8WtX4BLo8+iMzi2bzp6Ujrtlzd4o9la5 +cj0O+496lCf4edTlK0Ah6DpefjvtO07nyoboFnLHrXHNap5MYZDw3EbYsf/FRjL7 +Gq23+e0igcnTYJiB+9R+OffwR/KvTp1z3tAVsUf88RlJNtWGUB8AEFP8/Bwy62Gx +Dc8qzoaeoCha+LOwlDuinxcwJlFIsjyGw74QgW85LrfyGh4dyv3IbiLeATzafXRh +vqGvheJ2mXc2DT0cI2T+sfRutc/t1UnbUXt1KZyzgQKBgQDkWL1jq46IG62RhQJB +8hYhJvFzNc/2SdzHesCxVLxA+pLOkAazDEeYyUQ75tGlamW0sGgDcXj9oJp1O3/+ +kYHftrxfHOt4+V7//Mo/rwP0M2Y1l6qKCeAcY+4psRu2YQ+HOjqE9+6i8nHBKiou +Thd8Rs96aVmxlDFnvZtsVgBisQKBgQDP8qFENTV11JaRRISMZwt8n2vypFRNDKmg +nnGRE2xpzkpVX6tmRY7SrGgNc95SEO9lMLnQ1DQONv7Yw/up7Yj/tGmw37g8rAKj +zDDs7wHe1dBVw+wlM+4a28JlalVnQYOURMOqzcG35YMBxiCYUim80PdqLloE6FLr +4PZEy17BUwKBgQCMjsc9k/uvcoIbwikKmM7gZ01W4rf5XawGKlx0i7k5skQt3GAT +VKq5tKJI0SMZVG34lGHiRLX6QSLyqMZ31+9+2sgHMBEOLUo5/swr+TpQ1lbDBHHY +eI24TBbtGPT7BbH+RmyBLvB44w38nkzKpg001Y2fRzwL4DGtLvx96k5gcQKBgFW0 +l5joIT+OPfxjdAn2Enrrre8UoZYcCPGlPANiMQWuu15Sju8Y7hOQcVZSEihayIA5 +Q+x4+Xd+XSz0IY5Y02Uoc4Mtwd5nurLN3sBYhbnVAAfJN1PiAlnZh1aLK+Xhz5xV +dxu3sAbeNk+N3DNLcd5bdg2ySvHI2xxS3M1f0I73AoGAHyIZ5TGbrnOPUtqFjUrr +cnVv9HE5xN8d9XmmTGoR7jcOFaQFPnDX3XnNCMdhdPxIiNmQWXqlLVBWJa6z/wwR +rKPjKpXU/OD6XQ6+ywHyYWT0u7xdR9Mj9ZhAveXbjBuuK6jC2u2gYWslOUJOc5JD +BzB9RGx1kJOYPqhd3nyeNLY= +-----END PRIVATE KEY----- +` +) + type game struct { } func (g *game) Handle(r http_api.IRouter) { - r.GET("/get", http_api.WrapHandler(g.get)) + r.GET("/login", http_api.WrapHandler(g.login)) + + group := r.Group("", http_api.JWT(jwt.SigningMethodRS256, loadKey)) + { + group.GET("/get", http_api.WrapHandler(g.get)) + } +} + +func (g *game) login(c *gin.Context) (interface{}, error) { + key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey)) + if err != nil { + return nil, err + } + token, err := http_api.Token(jwt.SigningMethodRS256, key, 20*time.Second) + if err != nil { + return nil, err + } + return token, nil } func (g *game) get(c *gin.Context) (interface{}, error) { @@ -18,6 +81,11 @@ func (g *game) get(c *gin.Context) (interface{}, error) { return 100, nil } +func loadKey() (interface{}, error) { + + return jwt.ParseRSAPublicKeyFromPEM([]byte(publicKey)) +} + func main() { config := http_api.Config{ Name: "game", @@ -27,7 +95,7 @@ func main() { KeyFile: "", } s := http_api.NewHTTPServer(config) - defer s.Stop() + defer s.Close() s.AddHandler(&game{}) diff --git a/https/http_api/http.go b/https/http_api/http.go index 14a3237..5588a06 100644 --- a/https/http_api/http.go +++ b/https/http_api/http.go @@ -2,16 +2,21 @@ package http_api import ( "context" + "fmt" "net/http" + "strings" "time" "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" "github.com/pyihe/go-pkg/errors" "github.com/pyihe/go-pkg/syncs" "github.com/swaggo/files" "github.com/swaggo/gin-swagger" ) +const Authorization = "Authorization" + type IRouter = gin.IRouter // response 回复格式 @@ -83,7 +88,7 @@ func (s *HttpServer) AddHandler(handler APIHandler) { handler.Handle(engine.Group(prefix)) } -func (s *HttpServer) Stop() error { +func (s *HttpServer) Close() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -94,6 +99,38 @@ func (s *HttpServer) Stop() error { return nil } +func JWT(method jwt.SigningMethod, loadKey func() (interface{}, error)) gin.HandlerFunc { + return func(c *gin.Context) { + var err error + var token *jwt.Token + var header = c.Request.Header + var tokenStr = header.Get(Authorization) + + if strings.HasPrefix(tokenStr, "Bearer") { + var msg = strings.Split(tokenStr, " ") + if len(msg) != 2 || msg[0] != "Bearer" { + fmt.Println(0) + goto end + } + tokenStr = msg[1] + } + fmt.Println(1) + token, err = jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) { + if loadKey != nil { + return loadKey() + } + return nil, nil + }, jwt.WithValidMethods([]string{method.Alg()})) + + end: + if err != nil || token == nil || !token.Valid { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + c.Next() + } +} + func MidCORS() gin.HandlerFunc { return func(c *gin.Context) { var header = c.Writer.Header() @@ -139,3 +176,12 @@ func WrapHandler(handler func(*gin.Context) (interface{}, error)) func(*gin.Cont } } } + +func Token(method jwt.SigningMethod, key interface{}, expire time.Duration) (string, error) { + var now = jwt.TimeFunc() + return jwt.NewWithClaims(method, jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(now.Add(expire)), + NotBefore: jwt.NewNumericDate(now), + IssuedAt: jwt.NewNumericDate(now), + }).SignedString(key) +}