package tokenservicelogic import ( "ark-permission/internal/domain" "ark-permission/internal/entity" "bytes" "crypto/sha256" "encoding/hex" "fmt" "github.com/golang-jwt/jwt/v4" "time" ) var generateAccessTokenFunc = generateAccessToken var generateRefreshTokenFunc = generateRefreshToken func generateAccessToken(token entity.Token, data any, sign string) (string, error) { claim := entity.Claims{ Data: data, RegisteredClaims: jwt.RegisteredClaims{ ID: token.ID, ExpiresAt: jwt.NewNumericDate(time.Unix(int64(token.ExpiresIn), 0)), Issuer: "permission", }, } accessToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claim). SignedString([]byte(sign)) if err != nil { return "", domain.TokenClaimError(err.Error()) } return accessToken, nil } func generateRefreshToken(accessToken string) string { buf := bytes.NewBufferString(accessToken) h := sha256.New() _, _ = h.Write(buf.Bytes()) return hex.EncodeToString(h.Sum(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, domain.TokenUnexpectedSigningErr(fmt.Sprintf("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(token *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{}, domain.TokenTokenValidateErr("token valid error") } return claims, nil } func parseClaims(accessToken string, secret string, validate bool) (claims, error) { claimMap, err := parseToken(accessToken, secret, validate) if err != nil { return claims{}, err } claimsData, ok := claimMap["data"].(map[string]any) if ok { return convertMap(claimsData), nil } return claims{}, domain.TokenClaimError("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 }