package middleware import ( "errors" "os" "strings" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "github.com/niangaodev/art-code/repositories" "github.com/niangaodev/art-code/utils" ) // JWT密钥 var jwtSecret = []byte(getJWTSecret()) // getJWTSecret 获取JWT密钥,优先从环境变量获取,否则使用默认值 func getJWTSecret() string { secret := os.Getenv("JWT_SECRET") if secret == "" { return "your-secret-key" // 开发环境默认值,生产环境必须通过环境变量设置 } return secret } // Claims JWT声明结构 type Claims struct { UserID uint `json:"userId"` Username string `json:"username"` Role string `json:"role"` RoleID uint `json:"roleId"` jwt.RegisteredClaims } // GenerateToken 生成JWT令牌 func GenerateToken(userID uint, username, role string) (string, int64, error) { // 设置令牌过期时间为7天 expireTime := time.Now().Add(7 * 24 * time.Hour) expireUnix := expireTime.Unix() // 获取用户的RoleID var roleID uint userRole, err := repositories.GetRoleByName(role) if err == nil && userRole != nil { roleID = userRole.ID } // 创建声明 claims := Claims{ UserID: userID, Username: username, Role: role, RoleID: roleID, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(expireTime), IssuedAt: jwt.NewNumericDate(time.Now()), Subject: "admin-token", }, } // 创建令牌 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) // 签名令牌 tokenString, err := token.SignedString(jwtSecret) if err != nil { return "", 0, err } return tokenString, expireUnix, nil } // ParseToken 解析JWT令牌 func ParseToken(tokenString string) (*Claims, error) { // 解析令牌 token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { return jwtSecret, nil }) if err != nil { return nil, err } // 验证令牌 if claims, ok := token.Claims.(*Claims); ok && token.Valid { return claims, nil } return nil, errors.New("invalid token") } // AuthMiddleware JWT认证中间件 func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 从请求头中获取令牌 authHeader := c.GetHeader("Authorization") if authHeader == "" { utils.Error(c, 401, "登录已过期,请重新登录") c.Abort() return } // 检查令牌格式 parts := strings.SplitN(authHeader, " ", 2) if !(len(parts) == 2 && parts[0] == "Bearer") { utils.Error(c, 401, "登录已过期,请重新登录") c.Abort() return } // 解析令牌 claims, err := ParseToken(parts[1]) if err != nil { utils.Error(c, 401, "登录已过期,请重新登录") c.Abort() return } // 将用户信息存储到上下文 c.Set("userID", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) c.Set("roleID", claims.RoleID) c.Next() } } // RoleMiddleware 角色验证中间件 (Legacy support) func RoleMiddleware(roles ...string) gin.HandlerFunc { return func(c *gin.Context) { // 从上下文中获取用户角色 role, exists := c.Get("role") if !exists { utils.Error(c, 401, "未授权,请重新登录") c.Abort() return } // 检查用户角色是否在允许列表中 allowed := false for _, r := range roles { if role == r { allowed = true break } } if !allowed { utils.Error(c, 403, "权限不足") c.Abort() return } c.Next() } } // PermissionMiddleware 权限验证中间件 func PermissionMiddleware(resource, action string) gin.HandlerFunc { return func(c *gin.Context) { // 获取用户RoleID roleIDInterface, exists := c.Get("roleID") if !exists { // 尝试从role name获取 roleName, exists := c.Get("role") if !exists { utils.Error(c, 401, "未授权,请重新登录") c.Abort() return } role, err := repositories.GetRoleByName(roleName.(string)) if err != nil || role == nil { utils.Error(c, 403, "角色不存在") c.Abort() return } roleIDInterface = role.ID } roleID := roleIDInterface.(uint) // 获取该角色的所有权限 permissions, err := repositories.GetPermissionsByRoleID(roleID) if err != nil { utils.Error(c, 500, "权限校验失败") c.Abort() return } // 检查是否有匹配的权限 allowed := false for _, p := range permissions { if p.Resource == resource && p.Action == action { allowed = true break } } if !allowed { utils.Error(c, 403, "权限不足") c.Abort() return } c.Next() } }