jwt.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package middleware
  2. import (
  3. "app/commons/config"
  4. "app/commons/core/redisclient"
  5. "context"
  6. "errors"
  7. "fmt"
  8. "github.com/golang-jwt/jwt/v5"
  9. "strings"
  10. "time"
  11. )
  12. type Member struct {
  13. ID int64
  14. //Address string
  15. OpenId string
  16. Uid string
  17. }
  18. // Secret key used to sign the JWT token (In production, use environment variables to keep it secure)
  19. var jwtSecretByte = []byte("magic.node.secret.20251212")
  20. var jwtExpireDuration = int64(24) // in seconds
  21. var jwtIssuer = "issuer"
  22. var jwtConf *config.JWT
  23. func conf() *config.JWT {
  24. if jwtConf == nil {
  25. jwtConf = config.EnvConf().JWT
  26. }
  27. if jwtConf.SigningKey != "" {
  28. jwtSecretByte = []byte(jwtConf.SigningKey)
  29. }
  30. if jwtConf.ExpiresTime > 0 {
  31. jwtExpireDuration = jwtConf.ExpiresTime
  32. }
  33. if jwtConf.Issuer != "" {
  34. jwtIssuer = jwtConf.Issuer
  35. }
  36. //core.Log.Infof("Issuer:%s ExpiresTime:%dh SigningKey:%s", jwtIssuer, jwtExpireDuration, jwtSecretByte)
  37. return jwtConf
  38. }
  39. // MyClaims 定义了JWT中的自定义声明
  40. //
  41. // Address string `json:"address"`
  42. type MyClaims struct {
  43. UserID int64 `json:"userId"`
  44. OpenId string `json:"openId"`
  45. Uid string `json:"uid"`
  46. jwt.RegisteredClaims
  47. }
  48. // GenerateJWT 根据用户信息生成JWT
  49. func GenerateJWT(user Member) (string, error) {
  50. if jwtConf == nil {
  51. conf()
  52. }
  53. // 设置JWT的过期时间
  54. d := time.Duration(jwtExpireDuration) * time.Hour
  55. expirationTime := time.Now().Add(d)
  56. // 创建JWT的声明
  57. claims := MyClaims{
  58. UserID: user.ID,
  59. OpenId: user.OpenId,
  60. Uid: user.Uid,
  61. RegisteredClaims: jwt.RegisteredClaims{
  62. ID: fmt.Sprintf("%d", user.ID), // 设置ID
  63. ExpiresAt: jwt.NewNumericDate(expirationTime), // 设置过期时间
  64. Issuer: jwtIssuer, // 设置签发者
  65. },
  66. }
  67. // 使用HS256算法签署JWT
  68. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  69. // 生成并返回签名后的JWT字符串
  70. tokenString, err := token.SignedString(jwtSecretByte)
  71. if err != nil {
  72. return "", err
  73. }
  74. return tokenString, nil
  75. }
  76. // ParseJWT 解析和验证JWT
  77. func ParseJWT(tokenString string) (*MyClaims, error) {
  78. if jwtConf == nil {
  79. conf()
  80. }
  81. // 定义一个空的声明对象
  82. claims := &MyClaims{}
  83. // 去掉 "Bearer " 部分
  84. tokenString = strings.TrimPrefix(tokenString, "Bearer ")
  85. // 解析JWT
  86. token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
  87. // 验证签名算法
  88. if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
  89. return nil, errors.New("unexpected signing method")
  90. }
  91. return jwtSecretByte, nil
  92. })
  93. if err != nil || !token.Valid {
  94. return nil, errors.New("invalid token")
  95. }
  96. return claims, nil
  97. }
  98. // SetUserCurrentToken 设置用户当前有效token
  99. func SetUserCurrentToken(userID int64, tokenString string, expiration time.Duration) error {
  100. tokenString = strings.TrimPrefix(tokenString, "Bearer ")
  101. key := fmt.Sprintf("user_current_token:%d", userID)
  102. return redisclient.DefaultClient().Set(context.Background(), key, tokenString, expiration).Err()
  103. }
  104. // IsCurrentValidToken 检查token是否为用户当前有效token
  105. func IsCurrentValidToken(userID int64, tokenString string) bool {
  106. tokenString = strings.TrimPrefix(tokenString, "Bearer ")
  107. key := fmt.Sprintf("user_current_token:%d", userID)
  108. currentToken, err := redisclient.DefaultClient().Get(context.Background(), key).Result()
  109. if err != nil {
  110. return false // 如果获取失败,说明没有有效token或已过期
  111. }
  112. return currentToken == tokenString // 检查是否为当前有效token
  113. }