81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
// 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")
|
||
}
|