/** * package middleware * 作用:JWT认证中间件 */ package middleware import ( "net/http" "xk-websocket-v2/internal/utils" "github.com/gin-gonic/gin" ) /** * JWTAuthMiddleware * * 功能:JWT认证中间件 * * 作用: * 1. 从HTTP请求头或查询参数中提取JWT Token * 2. 验证Token的有效性和过期时间 * 3. 从Token中解析出用户ID * 4. 将用户ID注入到Gin Context中,供后续处理器使用 * 5. 如果Token无效或缺失,返回401未授权错误 * * 使用场景: * - 需要用户登录才能访问的API接口 * - 需要在处理器中获取当前用户信息的接口 * * @returns gin.HandlerFunc 中间件处理函数 */ func JWTAuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 步骤1: 从HTTP请求头中获取Token(标准方式) token := c.GetHeader("Authorization") if token == "" { // 步骤2: 如果请求头中没有,尝试从查询参数获取(兼容旧代码) token = c.Query("token") } // 步骤3: 如果仍然没有Token,返回401未授权错误 if token == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少认证Token"}) c.Abort() // 终止请求处理 return } // 步骤4: 移除 "Bearer " 前缀(如果存在) // 标准JWT Token格式:Bearer if len(token) > 7 && token[:7] == "Bearer " { token = token[7:] } // 步骤5: 验证Token的有效性和过期时间 userID, err := utils.ValidateToken(token) if err != nil { // Token无效或已过期,返回401错误 c.JSON(http.StatusUnauthorized, gin.H{"error": "Token无效或已过期: " + err.Error()}) c.Abort() return } // 步骤6: 将解析出的用户ID注入到Context中 // 后续处理器可以通过 c.Get("user_id") 获取当前用户ID c.Set("user_id", userID) c.Next() // 继续执行下一个中间件或处理器 } } /** * OptionalJWTAuthMiddleware * * 功能:可选的JWT认证中间件(不强制要求认证) * * 作用: * 1. 如果请求中提供了Token,则验证Token并注入用户ID * 2. 如果没有提供Token,则继续执行,不返回错误 * 3. 适用于既支持登录用户访问,也支持匿名用户访问的接口 * * 使用场景: * - 公开接口,但登录用户可以获取更多信息 * - 兼容旧代码,不强制要求认证 * * @returns gin.HandlerFunc 中间件处理函数 */ func OptionalJWTAuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // 步骤1: 尝试从请求头或查询参数获取Token token := c.GetHeader("Authorization") if token == "" { token = c.Query("token") } // 步骤2: 如果提供了Token,则验证并注入用户ID if token != "" { // 移除 "Bearer " 前缀 if len(token) > 7 && token[:7] == "Bearer " { token = token[7:] } // 验证Token,如果有效则注入用户ID // 如果Token无效,不返回错误,继续执行(允许匿名访问) if userID, err := utils.ValidateToken(token); err == nil { c.Set("user_id", userID) } } // 步骤3: 继续执行,无论是否有Token c.Next() } }