package security import ( "errors" "time" "github.com/golang-jwt/jwt/v5" ) type WebClaims struct { UserID string `json:"user_id"` UID string `json:"uid"` Username string `json:"username"` SessionVersion int64 `json:"session_version"` TokenType string `json:"token_type"` jwt.RegisteredClaims } type WebTokenService struct { Secret []byte AccessTTL time.Duration } func (s WebTokenService) NewAccessToken(userID, uid, username string, sessionVersion int64) (string, time.Time, error) { now := time.Now() expires := now.Add(s.AccessTTL) claims := WebClaims{ UserID: userID, UID: uid, Username: username, SessionVersion: sessionVersion, TokenType: "web_access", RegisteredClaims: jwt.RegisteredClaims{Subject: userID, IssuedAt: jwt.NewNumericDate(now), ExpiresAt: jwt.NewNumericDate(expires)}, } token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(s.Secret) return token, expires, err } func (s WebTokenService) ParseAccessToken(raw string) (*WebClaims, error) { claims := new(WebClaims) token, err := jwt.ParseWithClaims(raw, claims, func(token *jwt.Token) (any, error) { if token.Method != jwt.SigningMethodHS256 { return nil, errors.New("不支持的签名算法") } return s.Secret, nil }) if err != nil || !token.Valid || claims.TokenType != "web_access" { return nil, errors.New("登录凭证无效或已过期") } return claims, nil }