package utils import ( "errors" "time" "github.com/golang-jwt/jwt/v5" ) var ( ErrInvalidToken = errors.New("invalid token") ErrExpiredToken = errors.New("token has expired") ) // Claims JWT 声明 type Claims struct { UserID uint `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } // JWTConfig JWT 配置 type JWTConfig struct { Secret string ExpireTime int // 过期时间(小时) } // JWTManager JWT 管理器 type JWTManager struct { config JWTConfig } // NewJWTManager 创建 JWT 管理器 func NewJWTManager(secret string, expireTime int) *JWTManager { return &JWTManager{ config: JWTConfig{ Secret: secret, ExpireTime: expireTime, }, } } // GenerateToken 生成 JWT Token func (m *JWTManager) GenerateToken(userID uint, username, role string) (string, error) { claims := &Claims{ UserID: userID, Username: username, Role: role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(m.config.ExpireTime) * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), Issuer: "novablog", }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(m.config.Secret)) } // ParseToken 解析 JWT Token func (m *JWTManager) ParseToken(tokenString string) (*Claims, error) { token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { return []byte(m.config.Secret), nil }) if err != nil { if errors.Is(err, jwt.ErrTokenExpired) { return nil, ErrExpiredToken } return nil, ErrInvalidToken } if claims, ok := token.Claims.(*Claims); ok && token.Valid { return claims, nil } return nil, ErrInvalidToken }