package jwt import ( "context" "encoding/json" "git.diulo.com/mogfee/kit/errors" "git.diulo.com/mogfee/kit/internal/xuuid" "github.com/golang-jwt/jwt/v5" "time" ) // iss : jwt签发者 // sub : 主题名称 // aud : 面向的用户,一般都是通过ip或者域名控制 // exp : jwt的有效时间(过期时间),这个有效时间必须要大于签发时间,对于交互接口来说,建议是预设5秒 // nbf : 在什么时候jwt开始生效(在此之前不可用) // iat : jwt的签发时间 // jti : 唯一标识,主要用来回避被重复使用攻击 type UserInfo struct { UserId int64 UserName string UserType string Permissions []string UniqueId string } func GetToken(key string, info *UserInfo) (token string, uniqId string, err error) { uniqId = xuuid.UUID() info.UniqueId = uniqId var tokenStr string ctime := time.Now().Unix() tokenStr, err = jwt.NewWithClaims(jwt.SigningMethodHS256, &jwt.MapClaims{ //jwt签发者 //"iss": "auth.diulo.com", //主题名称 //"sub": "www.diulo.com", // 面向的用户,一般都是通过ip或者域名控制 //"aud": "api.diulo.com", //jwt的有效时间(过期时间),这个有效时间必须要大于签发时间,对于交互接口来说,建议是预设5秒 "exp": ctime + 7200, //在什么时候jwt开始生效(在此之前不可用) "nbf": ctime, //jwt的签发时间 "iat": ctime, //唯一标识,主要用来回避被重复使用攻击 "jti": uniqId, "info": info, }).SignedString([]byte(key)) if err != nil { return } token, err = Encrypt(tokenStr, []byte(key), key) return } func Parse(ctx context.Context, key string, tokenStr string) (*UserInfo, error) { if tokenStr == "" { return nil, errors.Unauthorized("TOKEN_ERROR", "") } str, err := Decrypt(tokenStr, []byte(key), key) if err != nil { return nil, err } token, err := jwt.Parse(str, func(token *jwt.Token) (interface{}, error) { return []byte(key), nil }) if err != nil { return nil, err } if token.Valid { row := struct { Info *UserInfo }{} b, _ := json.Marshal(token.Claims) if err = json.Unmarshal(b, &row); err != nil { return nil, err } return row.Info, nil } else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) { return nil, errors.Unauthorized("TOKEN_EXPIRED", "") } return nil, errors.Unauthorized("TOKEN_ERROR", "") }