Files
nl-game-api/internal/middleware/middleware.go
2026-08-14 13:17:03 +08:00

81 lines
2.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package middleware 提供 Gin 中间件跨域、JWT 鉴权、超管校验
package middleware
import (
"strings"
"github.com/gin-gonic/gin"
"nl-game-api-gin/internal/database"
"nl-game-api-gin/internal/model"
"nl-game-api-gin/pkg/jwtutil"
"nl-game-api-gin/pkg/resp"
)
// CORS 跨域中间件:开发时前端(5173)与后端(8080)端口不同,需要放行跨域请求
func CORS() gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.GetHeader("Origin")
if origin != "" {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
}
// 预检请求直接返回 204
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
// Auth JWT 鉴权中间件:从 Authorization: Bearer xxx 中解析用户身份
// 校验通过后将 user_id 与 role 写入上下文供后续处理函数使用
func Auth() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
token := strings.TrimPrefix(authHeader, "Bearer ")
if token == "" || token == authHeader {
resp.Unauthorized(c, "请先登录")
return
}
claims, err := jwtutil.Parse(token)
if err != nil {
resp.Unauthorized(c, "登录已过期,请重新登录")
return
}
// 查库校验账号仍然有效:否则封禁/删除的用户在 Token 过期前仍可操作全部接口
var user model.User
if err := database.DB.Select("status").First(&user, claims.UserID).Error; err != nil {
resp.Unauthorized(c, "账号不存在,请重新登录")
return
}
if user.Status == model.UserStatusBanned {
resp.Forbidden(c, "账号已被禁用")
return
}
// 身份信息写入请求上下文
c.Set("user_id", claims.UserID)
c.Set("role", claims.Role)
c.Next()
}
}
// AdminOnly 超管校验中间件:需在 Auth 之后使用,非超管直接拒绝
func AdminOnly() gin.HandlerFunc {
return func(c *gin.Context) {
if c.GetInt("role") != model.RoleAdmin {
resp.Forbidden(c, "仅超级管理员可操作")
return
}
c.Next()
}
}
// UID 从上下文取当前登录用户ID的快捷方法
func UID(c *gin.Context) int {
return c.GetInt("user_id")
}