package jwt import ( "errors" "time" jwtv5 "github.com/golang-jwt/jwt/v5" ) var ( ErrTokenValid = errors.New("未知错误") ErrTokenExpired = errors.New("token已过期") ErrTokenNotValidYet = errors.New("token尚未激活") ErrTokenMalformed = errors.New("这不是一个token") ErrTokenSignatureInvalid = errors.New("无效签名") ErrTokenInvalid = errors.New("无法处理此token") ) // BaseClaims 基础Claims type BaseClaims struct { ID string `json:"userId"` Account string `json:"account"` } // CustomClaims 自定义Claims type CustomClaims struct { BaseClaims BufferTime int64 `json:"bufferTime"` jwtv5.RegisteredClaims } // JWT JWT工具 type JWT struct { SigningKey []byte } // NewJWT 创建JWT实例 func NewJWT(signingKey string) *JWT { return &JWT{ SigningKey: []byte(signingKey), } } // CreateClaims 创建Claims func (j *JWT) CreateClaims(baseClaims BaseClaims, bufferTime, expiresTime time.Duration, issuer string) CustomClaims { return CustomClaims{ BaseClaims: baseClaims, BufferTime: int64(bufferTime / time.Second), RegisteredClaims: jwtv5.RegisteredClaims{ Audience: jwtv5.ClaimStrings{"sundynix"}, NotBefore: jwtv5.NewNumericDate(time.Now().Add(-1000)), ExpiresAt: jwtv5.NewNumericDate(time.Now().Add(expiresTime)), Issuer: issuer, }, } } // CreateToken 创建token func (j *JWT) CreateToken(claims CustomClaims) (string, error) { token := jwtv5.NewWithClaims(jwtv5.SigningMethodHS256, claims) return token.SignedString(j.SigningKey) } // ParseToken 解析token func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) { token, err := jwtv5.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwtv5.Token) (interface{}, error) { return j.SigningKey, nil }) if err != nil { switch { case errors.Is(err, jwtv5.ErrTokenExpired): return nil, ErrTokenExpired case errors.Is(err, jwtv5.ErrTokenNotValidYet): return nil, ErrTokenNotValidYet case errors.Is(err, jwtv5.ErrTokenMalformed): return nil, ErrTokenMalformed case errors.Is(err, jwtv5.ErrTokenSignatureInvalid): return nil, ErrTokenSignatureInvalid default: return nil, ErrTokenInvalid } } if token != nil { if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { return claims, nil } } return nil, ErrTokenInvalid } // GetTokenFromHeader 从Authorization头中提取token func GetTokenFromHeader(authHeader string) string { if len(authHeader) > 7 && authHeader[:7] == "Bearer " { return authHeader[7:] } return authHeader }