package middleware import ( "Cold_Logistic/internal/pkg/common/codex" "Cold_Logistic/internal/pkg/common/constant" "Cold_Logistic/internal/pkg/utils/headutil" "Cold_Logistic/internal/server/domain/domainservice" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/core" "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/errors" "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/log" "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/util/authutil" "time" ) func Auth() gin.HandlerFunc { return func(c *gin.Context) { tokenType, token, err := headutil.ParseAuthHead(c) if err != nil { core.WriteResponse(c, errors.WithCodeOnce(err, codex.ErrInvalidAuthHeader, err.Error()), nil) c.Abort() return } switch tokenType { case constant.AuthTokenTypeBearer: var jwtClaim *jwt.MapClaims jwtClaim, err = authutil.ParseToken(token, "") if err != nil { core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil) c.Abort() return } var accountId int accountId, err = verifyToken(c, token, jwtClaim) if err != nil { core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil) c.Abort() return } if c.FullPath() != "/clodLogistic/app/api/v1/myself/refreshToken" { if !jwtClaim.VerifyExpiresAt(time.Now().Unix(), false) { core.WriteResponse(c, errors.WrapC(err, codex.ErrStatusForbidden, ""), nil) c.Abort() return } if err = refreshToken(c, jwtClaim); err != nil { core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil) c.Abort() return } } err = setTokenInfo(c, accountId) if err != nil { core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil) c.Abort() return } default: core.WriteResponse(c, errors.WithCode(codex.ErrSignatureInvalid, "unrecognized Authorization header."), nil) c.Abort() return } c.Next() } } func verifyToken(c *gin.Context, token string, claim *jwt.MapClaims) (int, error) { clMap := *claim _, ok := clMap["iss"].(string) if !ok { return -1, errors.New("account token iss invalid") } uid, ok := clMap["uid"].(float64) if !ok { return -1, errors.New("account token iss invalid") } accountId := int(uid) redisT, err := domainservice.GetToken(c, accountId) if err != nil { return -1, errors.WithStackOnce(err) } if redisT == "" { return -1, errors.WithCode(codex.ErrSignatureInvalid, "Parse Authorization token fail.") } if redisT != token { return -1, errors.New("account token iss invalid") } return accountId, nil } // refreshToken 刷新token func refreshToken(ctx *gin.Context, claim *jwt.MapClaims) error { clMap := *claim accId := int(clMap["uid"].(float64)) exp := time.Now().Add(2 * time.Hour).Unix() expTime := time.Unix(int64(clMap["exp"].(float64)), 0) // 还有10分钟过期时发放新token if expTime.Sub(time.Now()) <= 10*time.Minute { newToken := authutil.Sign(accId, "", constant.CCLAppletLoginJWTISS, "", exp) ctx.Header("new-accessToken", newToken) } return nil } func setTokenInfo(c *gin.Context, accountId int) error { tokenInfo, err := domainservice.GetTokenInfoById(c, accountId) if err != nil { return errors.WithStackOnce(err) } c.Set(constant.TokenInfoKey, tokenInfo) // logger 补充accountId信息 AccountIdLogger := c.Value(log.GetContextKey()).(log.Logger) AccountIdLogger = AccountIdLogger.WithValues("accountId", tokenInfo.AccountId) c.Set(log.GetContextKey(), AccountIdLogger) return nil }