// =========================================== // 多班级版班级管理系统 - Go 后端 // // 开发者: Canglan // 联系方式: admin@sea-studio.top // 版权归属: Sea Network Technology Studio // 许可证: Apache License 2.0 // // 版权所有 © Sea Network Technology Studio // =========================================== package jwt import ( "fmt" "time" goJwt "github.com/golang-jwt/jwt/v5" "hz-gitea.sea-studio.top/canglan/SharedClassManager/internal/config" ) // getSigningMethod 根据配置返回对应的签名算法 func getSigningMethod(algorithm string) goJwt.SigningMethod { switch algorithm { case "HS384": return goJwt.SigningMethodHS384 case "HS512": return goJwt.SigningMethodHS512 default: return goJwt.SigningMethodHS256 } } // Claims JWT 载荷结构(与 Python 版完全兼容) type Claims struct { UserID int `json:"user_id"` Username string `json:"username"` UserType string `json:"user_type"` StudentID *int `json:"student_id"` Role string `json:"role"` RealName string `json:"real_name"` ClassID *int `json:"class_id"` NeedChangePassword bool `json:"need_change_password"` goJwt.RegisteredClaims } // CreateToken 创建 JWT Token func CreateToken(userID int, username, userType string, studentID *int, role, realName string, classID *int, needChangePassword bool) (string, error) { now := time.Now() cfg := config.AppConfig claims := Claims{ UserID: userID, Username: username, UserType: userType, StudentID: studentID, Role: role, RealName: realName, ClassID: classID, NeedChangePassword: needChangePassword, RegisteredClaims: goJwt.RegisteredClaims{ ExpiresAt: goJwt.NewNumericDate(now.Add(time.Duration(cfg.JWTExpireMinutes) * time.Minute)), IssuedAt: goJwt.NewNumericDate(now), Issuer: cfg.AppName, }, } token := goJwt.NewWithClaims(getSigningMethod(cfg.JWTAlgorithm), claims) return token.SignedString([]byte(cfg.JWTSecretKey)) } // VerifyToken 验证 JWT Token,返回解析后的载荷 func VerifyToken(tokenStr string) (*Claims, error) { cfg := config.AppConfig token, err := goJwt.ParseWithClaims(tokenStr, &Claims{}, func(t *goJwt.Token) (interface{}, error) { if _, ok := t.Method.(*goJwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("不支持的签名算法: %v", t.Header["alg"]) } return []byte(cfg.JWTSecretKey), nil }) if err != nil { return nil, fmt.Errorf("token 验证失败: %w", err) } claims, ok := token.Claims.(*Claims) if !ok || !token.Valid { return nil, fmt.Errorf("token 无效") } return claims, nil }