| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package auth
- import (
- "errors"
- "time"
- "perms-system-server/internal/consts"
- "perms-system-server/internal/middleware"
- "github.com/golang-jwt/jwt/v4"
- )
- var ErrTokenTypeMismatch = errors.New("token type mismatch")
- // ParseWithHMAC 转发到 middleware 包的统一 JWT 解析入口。保留本别名以兼容旧调用方(测试与
- // 历史 logic 代码);真实实现已经上移到 middleware 层,避免 middleware↔auth 循环依赖,
- // 同时把"算法混淆防御"的审计覆盖收敛到唯一一个函数(见审计 L-N1)。
- func ParseWithHMAC(tokenStr, secret string, claims jwt.Claims) (*jwt.Token, error) {
- return middleware.ParseWithHMAC(tokenStr, secret, claims)
- }
- type RefreshClaims struct {
- TokenType string `json:"tokenType"`
- UserId int64 `json:"userId"`
- ProductCode string `json:"productCode"`
- TokenVersion int64 `json:"tokenVersion"`
- jwt.RegisteredClaims
- }
- func GenerateAccessToken(secret string, expireSeconds int64, userId int64, username, productCode, memberType string, tokenVersion int64) (string, error) {
- now := time.Now()
- claims := middleware.Claims{
- TokenType: consts.TokenTypeAccess,
- UserId: userId,
- Username: username,
- ProductCode: productCode,
- MemberType: memberType,
- TokenVersion: tokenVersion,
- RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(expireSeconds) * time.Second)),
- IssuedAt: jwt.NewNumericDate(now),
- },
- }
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString([]byte(secret))
- }
- func GenerateRefreshToken(secret string, expireSeconds int64, userId int64, productCode string, tokenVersion int64) (string, error) {
- now := time.Now()
- claims := RefreshClaims{
- TokenType: consts.TokenTypeRefresh,
- UserId: userId,
- ProductCode: productCode,
- TokenVersion: tokenVersion,
- RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(expireSeconds) * time.Second)),
- IssuedAt: jwt.NewNumericDate(now),
- },
- }
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString([]byte(secret))
- }
- // GenerateRefreshTokenWithExpiry 签发 refreshToken,使用绝对过期时间(用于 token 轮转场景)。
- func GenerateRefreshTokenWithExpiry(secret string, expiresAt time.Time, userId int64, productCode string, tokenVersion int64) (string, error) {
- now := time.Now()
- if !expiresAt.After(now) {
- return "", errors.New("refresh token has expired")
- }
- claims := RefreshClaims{
- TokenType: consts.TokenTypeRefresh,
- UserId: userId,
- ProductCode: productCode,
- TokenVersion: tokenVersion,
- RegisteredClaims: jwt.RegisteredClaims{
- ExpiresAt: jwt.NewNumericDate(expiresAt),
- IssuedAt: jwt.NewNumericDate(now),
- },
- }
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString([]byte(secret))
- }
- func ParseRefreshToken(tokenStr, secret string) (*RefreshClaims, error) {
- token, err := ParseWithHMAC(tokenStr, secret, &RefreshClaims{})
- if err != nil {
- return nil, err
- }
- claims, ok := token.Claims.(*RefreshClaims)
- if !ok || !token.Valid {
- return nil, jwt.ErrSignatureInvalid
- }
- if claims.TokenType != consts.TokenTypeRefresh {
- return nil, ErrTokenTypeMismatch
- }
- return claims, nil
- }
|