117 lines
3.3 KiB
Go
117 lines
3.3 KiB
Go
/**
|
||
* package middleware
|
||
* 作用:JWT认证中间件
|
||
*/
|
||
package middleware
|
||
|
||
import (
|
||
"log"
|
||
"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 <token>
|
||
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
|
||
}
|
||
|
||
// 调试日志:打印解析出的用户ID,帮助排查JWT问题
|
||
log.Printf("🔑 [JWT] 请求: %s %s | 解析出的用户ID: %s", c.Request.Method, c.Request.URL.Path, userID)
|
||
|
||
// 步骤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()
|
||
}
|
||
}
|
||
|