add
wangpengfei
2023-08-26 aca83ef7ccda31adc3eb2c057d4120c112115076
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package utils
 
import (
    "errors"
    "time"
 
    jwt "github.com/golang-jwt/jwt/v4"
 
    "srm/global"
    "srm/model/system/request"
)
 
type JWT struct {
    SigningKey []byte
}
 
var (
    TokenExpired     = errors.New("Token is expired")
    TokenNotValidYet = errors.New("Token not active yet")
    TokenMalformed   = errors.New("That's not even a token")
    TokenInvalid     = errors.New("Couldn't handle this token:")
)
 
func NewJWT() *JWT {
    return &JWT{
        []byte(global.GVA_CONFIG.JWT.SigningKey),
    }
}
 
func (j *JWT) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims {
    bf, _ := ParseDuration(global.GVA_CONFIG.JWT.BufferTime)
    ep, _ := ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
    claims := request.CustomClaims{
        BaseClaims: baseClaims,
        BufferTime: int64(bf / time.Second), // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
        RegisteredClaims: jwt.RegisteredClaims{
            Audience:  jwt.ClaimStrings{"GVA"},                   // 受众
            NotBefore: jwt.NewNumericDate(time.Now().Add(-1000)), // 签名生效时间
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(ep)),    // 过期时间 7天  配置文件
            Issuer:    global.GVA_CONFIG.JWT.Issuer,              // 签名的发行者
        },
    }
    return claims
}
 
// 创建一个token
func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) {
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(j.SigningKey)
}
 
// CreateTokenByOldToken 旧token 换新token 使用归并回源避免并发问题
func (j *JWT) CreateTokenByOldToken(oldToken string, claims request.CustomClaims) (string, error) {
    v, err, _ := global.GVA_Concurrency_Control.Do("JWT:"+oldToken, func() (interface{}, error) {
        return j.CreateToken(claims)
    })
    return v.(string), err
}
 
// 解析 token
func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) {
    token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
        return j.SigningKey, nil
    })
    if err != nil {
        if ve, ok := err.(*jwt.ValidationError); ok {
            if ve.Errors&jwt.ValidationErrorMalformed != 0 {
                return nil, TokenMalformed
            } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
                // Token is expired
                return nil, TokenExpired
            } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
                return nil, TokenNotValidYet
            } else {
                return nil, TokenInvalid
            }
        }
    }
    if token != nil {
        if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
            return claims, nil
        }
        return nil, TokenInvalid
 
    } else {
        return nil, TokenInvalid
    }
}