package jwt import ( "fmt" "time" "github.com/golang-jwt/jwt/v4" ) func GenerateAccessToken(token Token, data any, sign string, issuer string) (string, error) { claim := Claims{ Data: data, RegisteredClaims: jwt.RegisteredClaims{ ID: token.ID, ExpiresAt: jwt.NewNumericDate(time.Unix(int64(token.ExpiresIn), 0)), Issuer: issuer, }, } accessToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claim). SignedString([]byte(sign)) if err != nil { return "", err } return accessToken, nil } func ParseToken(accessToken string, secret string, validate bool) (jwt.MapClaims, error) { // 跳過驗證的解析 var token *jwt.Token var err error if validate { token, err = jwt.Parse(accessToken, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("token unexpected signing method: %v", token.Header["alg"]) } return []byte(secret), nil }) if err != nil { return jwt.MapClaims{}, err } } else { parser := jwt.NewParser(jwt.WithoutClaimsValidation()) token, err = parser.Parse(accessToken, func(_ *jwt.Token) (interface{}, error) { return []byte(secret), nil }) if err != nil { return jwt.MapClaims{}, err } } claims, ok := token.Claims.(jwt.MapClaims) if !ok && token.Valid { return jwt.MapClaims{}, fmt.Errorf("token valid error") } return claims, nil } func ParseClaims(accessToken string, secret string, validate bool) (DataClaims, error) { claimMap, err := ParseToken(accessToken, secret, validate) if err != nil { return DataClaims{}, err } claimsData, ok := claimMap["data"].(map[string]any) if ok { return convertMap(claimsData), nil } return DataClaims{}, fmt.Errorf("get data from claim map error") } func convertMap(input map[string]interface{}) map[string]string { output := make(map[string]string) for key, value := range input { switch v := value.(type) { case string: output[key] = v case fmt.Stringer: output[key] = v.String() default: output[key] = fmt.Sprintf("%v", value) } } return output }