| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- 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(),
- }
- }
|