package utils import ( "fmt" "time" "github.com/beego/beego/v2/server/web" "github.com/golang-jwt/jwt/v5" ) // LocalTokenClaims 本地JWT token的claims结构 type LocalTokenClaims struct { UserID uint `json:"user_id"` Username string `json:"username"` Role string `json:"role"` TokenType string `json:"token_type"` // "local" 标识为本地token jwt.RegisteredClaims } // GenerateLocalToken 生成本地JWT token func GenerateLocalToken(userID uint, username string, role string) (string, error) { // 从配置读取JWT密钥 jwtSecret, err := web.AppConfig.String("jwt_secret") if err != nil || jwtSecret == "" { jwtSecret = "default-secret-key-please-change-in-production" // 默认密钥 } // 设置token有效期为24小时 expirationTime := time.Now().Add(24 * time.Hour) // 创建claims claims := &LocalTokenClaims{ UserID: userID, Username: username, Role: role, TokenType: "local", RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(expirationTime), IssuedAt: jwt.NewNumericDate(time.Now()), Issuer: "shudao-local-auth", }, } // 创建token token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 签名token tokenString, err := token.SignedString([]byte(jwtSecret)) if err != nil { return "", fmt.Errorf("生成token失败: %v", err) } return tokenString, nil } // VerifyLocalToken 验证本地JWT token并返回claims func VerifyLocalToken(tokenString string) (*LocalTokenClaims, error) { // 从配置读取JWT密钥 jwtSecret, err := web.AppConfig.String("jwt_secret") if err != nil || jwtSecret == "" { jwtSecret = "default-secret-key-please-change-in-production" } // 解析token token, err := jwt.ParseWithClaims(tokenString, &LocalTokenClaims{}, func(token *jwt.Token) (interface{}, error) { // 验证签名方法 if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return []byte(jwtSecret), nil }) if err != nil { return nil, fmt.Errorf("解析token失败: %v", err) } // 验证token有效性 if claims, ok := token.Claims.(*LocalTokenClaims); ok && token.Valid { // 检查是否为本地token if claims.TokenType != "local" { return nil, fmt.Errorf("不是本地token") } return claims, nil } return nil, fmt.Errorf("token无效") } // ConvertLocalClaimsToTokenUserInfo 将本地token claims转换为TokenUserInfo func ConvertLocalClaimsToTokenUserInfo(claims *LocalTokenClaims) *TokenUserInfo { return &TokenUserInfo{ AccountID: fmt.Sprintf("local_%d", claims.UserID), ID: int64(claims.UserID), Name: claims.Username, UserCode: claims.Username, ContactNumber: "", TokenType: "local", Exp: claims.ExpiresAt.Unix(), Iat: claims.IssuedAt.Unix(), } }