package middleware import ( "net/http" "strings" "goblog/handlers" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) // tokenFromContext 统一从 Cookie 或 Authorization 头提取 JWT token // 优先读 Cookie(服务端渲染 + 同域 AJAX 自动携带),回退到 Authorization 头 func tokenFromContext(c *gin.Context) string { if tokenString, err := c.Cookie("token"); err == nil && tokenString != "" { return tokenString } authHeader := c.GetHeader("Authorization") if authHeader != "" { parts := strings.SplitN(authHeader, " ", 2) if len(parts) == 2 && parts[0] == "Bearer" { return parts[1] } } return "" } // JWT 认证中间件 func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { tokenString := tokenFromContext(c) if tokenString == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "缺少认证令牌"}) c.Abort() return } claims := &handlers.Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return handlers.JWTSecret(), nil }) if err != nil || !token.Valid { c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的令牌"}) c.Abort() return } c.Set("userID", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) c.Next() } } // 管理员权限中间件 func AdminRequired() gin.HandlerFunc { return func(c *gin.Context) { role, exists := c.Get("role") if !exists || role != "admin" { c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限"}) c.Abort() return } c.Next() } } // OptionalAuth 可选认证中间件(用于某些既支持游客又支持登录用户的接口/页面) func OptionalAuth() gin.HandlerFunc { return func(c *gin.Context) { tokenString := tokenFromContext(c) if tokenString == "" { c.Next() return } claims := &handlers.Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return handlers.JWTSecret(), nil }) if err == nil && token.Valid { c.Set("userID", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) } c.Next() } }