auth.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package middleware
  2. import (
  3. "Cold_Logistic/internal/pkg/common/codex"
  4. "Cold_Logistic/internal/pkg/common/constant"
  5. "Cold_Logistic/internal/pkg/utils/headutil"
  6. "Cold_Logistic/internal/server/domain/domainservice"
  7. "github.com/gin-gonic/gin"
  8. "github.com/golang-jwt/jwt/v4"
  9. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/core"
  10. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/errors"
  11. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/log"
  12. "gogs.baozhida.cn/Cold_Logistic_libs/pkg/contrib/util/authutil"
  13. "time"
  14. )
  15. func Auth() gin.HandlerFunc {
  16. return func(c *gin.Context) {
  17. tokenType, token, err := headutil.ParseAuthHead(c)
  18. if err != nil {
  19. core.WriteResponse(c, errors.WithCodeOnce(err, codex.ErrInvalidAuthHeader, err.Error()), nil)
  20. c.Abort()
  21. return
  22. }
  23. switch tokenType {
  24. case constant.AuthTokenTypeBearer:
  25. var jwtClaim *jwt.MapClaims
  26. jwtClaim, err = authutil.ParseToken(token, "")
  27. if err != nil {
  28. core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil)
  29. c.Abort()
  30. return
  31. }
  32. var accountId int
  33. accountId, err = verifyToken(c, token, jwtClaim)
  34. if err != nil {
  35. core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil)
  36. c.Abort()
  37. return
  38. }
  39. if c.FullPath() != "/clodLogistic/app/api/v1/myself/refreshToken" {
  40. if !jwtClaim.VerifyExpiresAt(time.Now().Unix(), false) {
  41. core.WriteResponse(c, errors.WrapC(err, codex.ErrStatusForbidden, ""), nil)
  42. c.Abort()
  43. return
  44. }
  45. if err = refreshToken(c, jwtClaim); err != nil {
  46. core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil)
  47. c.Abort()
  48. return
  49. }
  50. }
  51. err = setTokenInfo(c, accountId)
  52. if err != nil {
  53. core.WriteResponse(c, errors.WrapC(err, codex.ErrSignatureInvalid, "Parse Authorization token fail."), nil)
  54. c.Abort()
  55. return
  56. }
  57. default:
  58. core.WriteResponse(c, errors.WithCode(codex.ErrSignatureInvalid, "unrecognized Authorization header."), nil)
  59. c.Abort()
  60. return
  61. }
  62. c.Next()
  63. }
  64. }
  65. func verifyToken(c *gin.Context, token string, claim *jwt.MapClaims) (int, error) {
  66. clMap := *claim
  67. _, ok := clMap["iss"].(string)
  68. if !ok {
  69. return -1, errors.New("account token iss invalid")
  70. }
  71. uid, ok := clMap["uid"].(float64)
  72. if !ok {
  73. return -1, errors.New("account token iss invalid")
  74. }
  75. accountId := int(uid)
  76. redisT, err := domainservice.GetToken(c, accountId)
  77. if err != nil {
  78. return -1, errors.WithStackOnce(err)
  79. }
  80. if redisT == "" {
  81. return -1, errors.WithCode(codex.ErrSignatureInvalid, "Parse Authorization token fail.")
  82. }
  83. if redisT != token {
  84. return -1, errors.New("account token iss invalid")
  85. }
  86. return accountId, nil
  87. }
  88. // refreshToken 刷新token
  89. func refreshToken(ctx *gin.Context, claim *jwt.MapClaims) error {
  90. clMap := *claim
  91. accId := int(clMap["uid"].(float64))
  92. exp := time.Now().Add(2 * time.Hour).Unix()
  93. expTime := time.Unix(int64(clMap["exp"].(float64)), 0)
  94. // 还有10分钟过期时发放新token
  95. if expTime.Sub(time.Now()) <= 10*time.Minute {
  96. newToken := authutil.Sign(accId, "", constant.CCLAppletLoginJWTISS, "", exp)
  97. ctx.Header("new-accessToken", newToken)
  98. }
  99. return nil
  100. }
  101. func setTokenInfo(c *gin.Context, accountId int) error {
  102. tokenInfo, err := domainservice.GetTokenInfoById(c, accountId)
  103. if err != nil {
  104. return errors.WithStackOnce(err)
  105. }
  106. c.Set(constant.TokenInfoKey, tokenInfo)
  107. // logger 补充accountId信息
  108. AccountIdLogger := c.Value(log.GetContextKey()).(log.Logger)
  109. AccountIdLogger = AccountIdLogger.WithValues("accountId", tokenInfo.AccountId)
  110. c.Set(log.GetContextKey(), AccountIdLogger)
  111. return nil
  112. }