jwt.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package middleware
  2. import (
  3. "fmt"
  4. "github.com/gin-gonic/gin"
  5. "github.com/go-nunu/nunu-layout-advanced/pkg/helper/resp"
  6. "github.com/go-nunu/nunu-layout-advanced/pkg/log"
  7. "github.com/golang-jwt/jwt/v5"
  8. "github.com/spf13/viper"
  9. "go.uber.org/zap"
  10. "net/http"
  11. "regexp"
  12. )
  13. type JWT struct {
  14. key string
  15. }
  16. type MyCustomClaims struct {
  17. UserId int64
  18. jwt.RegisteredClaims
  19. }
  20. // NewJwt https://pkg.go.dev/github.com/golang-jwt/jwt/v5
  21. func NewJwt(conf *viper.Viper) *JWT {
  22. return &JWT{key: conf.GetString("security.jwt.key")}
  23. }
  24. func (j *JWT) GenToken() string {
  25. token := jwt.NewWithClaims(jwt.SigningMethodHS512, MyCustomClaims{
  26. UserId: 1,
  27. })
  28. // Sign and get the complete encoded token as a string using the key
  29. tokenString, err := token.SignedString(j.key)
  30. fmt.Println(tokenString, err)
  31. return tokenString
  32. }
  33. func (j *JWT) ParseToken(tokenString string) (*MyCustomClaims, error) {
  34. re, _ := regexp.Compile(`(?i)Bearer `)
  35. tokenString = re.ReplaceAllString(tokenString, "")
  36. token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  37. return []byte("AllYourBase"), nil
  38. })
  39. if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
  40. return claims, nil
  41. } else {
  42. return nil, err
  43. }
  44. }
  45. // StrictAuth 严格权限
  46. func StrictAuth(j *JWT, logger *log.Logger) gin.HandlerFunc {
  47. return func(ctx *gin.Context) {
  48. tokenString := ctx.Request.Header.Get("Authorization")
  49. if tokenString == "" {
  50. logger.WithContext(ctx).Warn("请求未携带token,无权限访问", zap.Any("data", map[string]interface{}{
  51. "url": ctx.Request.URL,
  52. "params": ctx.Params,
  53. }))
  54. resp.HandleError(ctx, http.StatusUnauthorized, 1, "no token", nil)
  55. ctx.Abort()
  56. return
  57. }
  58. // parseToken 解析token包含的信息
  59. claims, err := j.ParseToken(tokenString)
  60. if err != nil {
  61. logger.WithContext(ctx).Error("token error", zap.Any("data", map[string]interface{}{
  62. "url": ctx.Request.URL,
  63. "params": ctx.Params,
  64. }))
  65. resp.HandleError(ctx, http.StatusUnauthorized, 1, err.Error(), nil)
  66. ctx.Abort()
  67. return
  68. }
  69. // 继续交由下一个路由处理,并将解析出的信息传递下去
  70. ctx.Set("claims", claims)
  71. recoveryLoggerFunc(ctx, logger)
  72. ctx.Next()
  73. }
  74. }
  75. func NoStrictAuth(j *JWT, logger *log.Logger) gin.HandlerFunc {
  76. return func(ctx *gin.Context) {
  77. tokenString := ctx.Request.Header.Get("Authorization")
  78. if tokenString == "" {
  79. tokenString, _ = ctx.Cookie("accessToken")
  80. }
  81. if tokenString == "" {
  82. tokenString = ctx.Query("accessToken")
  83. }
  84. if tokenString == "" {
  85. ctx.Next()
  86. return
  87. }
  88. // parseToken 解析token包含的信息
  89. claims, err := j.ParseToken(tokenString)
  90. if err != nil {
  91. ctx.Next()
  92. return
  93. }
  94. // 继续交由下一个路由处理,并将解析出的信息传递下去
  95. ctx.Set("claims", claims)
  96. recoveryLoggerFunc(ctx, logger)
  97. ctx.Next()
  98. }
  99. }
  100. func recoveryLoggerFunc(ctx *gin.Context, logger *log.Logger) {
  101. userInfo := ctx.MustGet("claims").(*MyCustomClaims)
  102. logger.NewContext(ctx, zap.Int64("UserId", userInfo.UserId))
  103. }