package service import ( "cpdaily-new/internal/config" "errors" "time" "github.com/golang-jwt/jwt/v5" ) type Claims struct { UserID uint `json:"userId"` Username string `json:"username"` SchoolID string `json:"schoolId"` jwt.RegisteredClaims } type TokenPair struct { AccessToken string `json:"accessToken"` RefreshToken string `json:"refreshToken"` ExpiresIn int64 `json:"expiresIn"` } func GenerateTokens(userID uint, username, schoolID string) (*TokenPair, error) { now := time.Now() jwtCfg := config.Global.Jwt accessClaims := Claims{ UserID: userID, Username: username, SchoolID: schoolID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(jwtCfg.AccessExpire) * time.Second)), IssuedAt: jwt.NewNumericDate(now), Issuer: "cpdaily-new", }, } accessToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, accessClaims).SignedString([]byte(jwtCfg.Secret)) if err != nil { return nil, err } refreshClaims := Claims{ UserID: userID, Username: username, SchoolID: schoolID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(jwtCfg.RefreshExpire) * time.Second)), IssuedAt: jwt.NewNumericDate(now), Issuer: "cpdaily-new-refresh", }, } refreshToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, refreshClaims).SignedString([]byte(jwtCfg.Secret)) if err != nil { return nil, err } return &TokenPair{ AccessToken: accessToken, RefreshToken: refreshToken, ExpiresIn: int64(jwtCfg.AccessExpire), }, nil } func ValidateToken(tokenString string) (*Claims, error) { claims := &Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, errors.New("unexpected signing method") } return []byte(config.Global.Jwt.Secret), nil }) if err != nil { return nil, err } if !token.Valid { return nil, errors.New("invalid token") } return claims, nil } func RefreshTokens(refreshToken string) (*TokenPair, error) { claims, err := ValidateToken(refreshToken) if err != nil { return nil, errors.New("refresh token invalid or expired") } // 刷新时生成全新 token 对 return GenerateTokens(claims.UserID, claims.Username, claims.SchoolID) }