中间件体系
Hei Gin 的中间件系统分为三个层次:全局中间件、业务中间件和内置中间件。以下逐一介绍每个中间件的功能、配置和使用方式。
全局中间件
全局中间件注册在 Gin Engine 上,对所有请求生效。
1. Trace 中间件
文件:core/middleware/trace.go
Trace 中间件负责全链路追踪,为每个请求生成或透传唯一的 trace_id。
功能:
- 检查请求头中是否包含
trace_id - 如果存在,透传该 Trace ID
- 如果不存在,调用
utils.GenerateTraceID()生成新的 Trace ID(UUID 的十六进制编码,不含连字符) - 将 Trace ID 设置到 Gin Context 的
"trace_id"键中
注册方式:
import "hei-gin/core/middleware"
r.Use(middleware.Trace())使用方式:
// 在 Handler 中获取 Trace ID
traceID := c.GetString("trace_id")
// 使用 result 包自动在响应中包含 trace_id
import "hei-gin/core/result"
result.Success(c, data) // 响应中自动包含 "trace_id" 字段
result.Failure(c, message, code, data) // 同上响应示例:
{
"code": 200,
"message": "请求成功",
"data": {},
"success": true,
"trace_id": "a1b2c3d4e5f67890abcdef1234567890"
}2. AuthCheck 中间件
文件:core/middleware/auth_check.go
AuthCheck 中间件根据请求路径自动识别认证类型,对无需认证的路径放行,对需要认证的路径进行登录检查。
路由分流规则:
静态路径 (/favicon.ico, /docs, /redoc, /openapi.json, /v3/api-docs) -> 放行
OPTIONS 方法 -> 放行
/api/v{n}/public/* -> 放行(无需认证)
/api/v{n}/c/* -> 要求 C 端登录认证
/api/v{n}/b/* 或 /api/v{n}/<其他>/* -> 要求 B 端登录认证未通过认证的请求会收到 401 JSON 响应。
注册方式:
r.Use(middleware.AuthCheck())3. Recovery 中间件
文件:core/middleware/recovery.go
Recovery 中间件捕获 Gin 处理过程中发生的 panic,转换为友好的 JSON 错误响应。它替换了 Gin 默认的 Recovery 中间件,提供了业务异常(BusinessError)支持。
功能:
- 捕获所有 panic
- 如果是
*exception.BusinessError或exception.BusinessError,提取错误码和错误信息,通过result.Failure返回 200 状态码(业务码在 JSON body 中) - 如果是其他 panic,返回 500 "服务器内部错误"
- 处理 handler 链中通过
c.Error()收集的错误,返回 400
BusinessError 使用方式:
import "hei-gin/core/exception"
// 使用构造函数创建业务异常并 panic
panic(exception.NewBusinessError("用户名或密码错误", 400))
// 或直接使用结构体字面量
panic(exception.BusinessError{
Code: 400,
Message: "用户名或密码错误",
})对应响应:
{
"code": 400,
"message": "用户名或密码错误",
"data": null,
"success": false,
"trace_id": "a1b2c3d4..."
}注册方式:
r.Use(middleware.Recovery())4. CORS 中间件
文件:core/middleware/cors.go
CORS 中间件处理跨域请求,配置项来源于 config.yaml 中的 cors 配置段。
功能:
- 处理 OPTIONS 预检请求
- 配置允许的来源、方法、头
- 支持 Allow Credentials 配置
注册方式:
r.Use(middleware.CORS())业务中间件
业务中间件按需注册到具体的路由组上。以下中间件均位于 core/auth/middleware 包,导入方式:
import middleware "hei-gin/core/auth/middleware"5. HeiCheckLogin(B 端登录验证)
文件:core/auth/middleware/check_login.go
验证请求携带的 JWT Token 是否有效。
函数签名:
func HeiCheckLogin(loginType ...string) gin.HandlerFuncloginType 默认为 "BUSINESS"。传入 "CONSUMER" 可复用此中间件做 C 端登录检查。
功能:
- 从
Authorization头中提取 Bearer Token - 解析 JWT Token 的有效性
- 验证 Token 是否在禁用列表中
- 从 Redis 中读取会话信息
- 将会话信息注入到 Context 中
注册方式:
bApi := r.Group("/api/v1/b", middleware.HeiCheckLogin())6. HeiClientCheckLogin(C 端登录验证)
文件:core/auth/middleware/client_check_login.go
C 端的专用登录验证中间件,内部委托给 HeiCheckLogin("CONSUMER")。
函数签名:
func HeiClientCheckLogin() gin.HandlerFunc注册方式:
cApi := r.Group("/api/v1/c", middleware.HeiClientCheckLogin())7. HeiCheckPermission(B 端权限检查)
文件:core/auth/middleware/check_permission.go
检查当前登录用户是否拥有指定的权限。同时具有权限自动注册功能。
函数签名:
func HeiCheckPermission(permissions []string, mode ...string) gin.HandlerFuncpermissions:权限代码列表(如[]string{"sys:user:list"})mode:匹配模式,默认为"AND"(需要全部权限),传入"OR"则满足任意一个即可
功能:
- 自动注册权限代码到权限扫描系统
- 检查用户是否为 SUPER_ADMIN,是则直接放行
- 从 Redis 缓存中获取用户权限集合
- 使用权限匹配器进行通配符匹配
- 匹配成功则放行,失败则返回 403
注册方式:
// 单个权限(AND 模式)
sysApi.GET("/user/list",
middleware.HeiCheckPermission([]string{"sys:user:list"}),
handler.UserList,
)
// 多个权限(OR 模式:任意一个匹配即可)
sysApi.POST("/user/save",
middleware.HeiCheckPermission([]string{"sys:user:create", "sys:user:update"}, "OR"),
handler.UserSave,
)8. HeiClientCheckPermission(C 端权限检查)
文件:core/auth/middleware/client_check_permission.go
C 端的权限检查中间件,内部委托给 heiCheckPermissionInner("CONSUMER", ...)。
函数签名:
func HeiClientCheckPermission(permissions []string, mode ...string) gin.HandlerFunc用法与 HeiCheckPermission 相同,但检查的是 C 端用户的权限。
注册方式:
clientApi.GET("/order/list",
middleware.HeiClientCheckPermission([]string{"client:order:list"}),
handler.OrderList,
)9. HeiCheckRole(B 端角色检查)
文件:core/auth/middleware/check_role.go
检查当前用户是否拥有指定的角色。
函数签名:
func HeiCheckRole(roles []string, mode ...string) gin.HandlerFuncroles:角色代码列表mode:匹配模式,默认为"AND"(需要全部角色),传入"OR"则满足任意一个即可
功能:
- 检查用户是否为 SUPER_ADMIN,是则直接放行
- 从 Redis/DB 获取用户角色
- 检查用户是否拥有指定的角色代码
注册方式:
// 单个角色
sysApi.DELETE("/user/delete",
middleware.HeiCheckRole([]string{"admin"}),
handler.UserDelete,
)
// 多个角色(OR 模式:任意一个匹配即可)
sysApi.POST("/sys/config/save",
middleware.HeiCheckRole([]string{"admin", "operator"}, "OR"),
handler.ConfigSave,
)10. HeiClientCheckRole(C 端角色检查)
文件:core/auth/middleware/client_check_role.go
C 端的角色检查中间件。
函数签名:
func HeiClientCheckRole(roles []string, mode ...string) gin.HandlerFunc用法与 HeiCheckRole 相同,但检查的是 C 端用户的角色。
11. SysLog(操作日志录制)
文件:core/log/syslog.go
自动录制用户的操作日志,在 handler 执行完成后异步写入 sys_log 表。
函数签名:
func SysLog(name string) gin.HandlerFuncname:操作日志的名称(如 "新增用户"、"删除配置")
功能:
- 记录请求方法、路径、参数
- 自动捕获 handler 中的 panic(记录异常日志后重新 panic)
- 记录响应状态(SUCCESS / FAIL)
- 异步写入 sys_log 表(ent ORM)
注册方式:
import "hei-gin/core/log"
// 注册到具体路由
sysApi.POST("/user/save",
middleware.HeiCheckLogin(),
middleware.HeiCheckPermission([]string{"sys:user:create"}),
log.SysLog("新增用户"),
handler.UserSave,
)12. NoRepeat(防重复提交)
文件:core/auth/middleware/norepeat.go
防止用户在指定时间间隔内重复提交相同的请求。
函数签名:
func NoRepeat(interval int) gin.HandlerFuncinterval:防重复时间间隔,单位毫秒(ms)
原理:
- 基于请求的路径 + 参数 + 用户 ID + IP 生成缓存键
- 对请求参数(Query、Form、Body)计算 FNV-1a 64 位哈希值
- 在 Redis 中记录该哈希值和时间戳(TTL 为 3600 秒)
- 同一请求在指定间隔内重复提交会被拒绝(返回 429)
注册方式:
// 3 秒内禁止重复提交
sysApi.POST("/user/save",
middleware.HeiCheckLogin(),
middleware.HeiCheckPermission([]string{"sys:user:create"}),
middleware.NoRepeat(3000),
handler.UserSave,
)中间件链完整示例
一个典型的 B 端 API 路由注册:
import (
"github.com/gin-gonic/gin"
"hei-gin/core/middleware"
authMiddleware "hei-gin/core/auth/middleware"
"hei-gin/core/log"
)
// 在模块的 api.go 中
func RegisterRoutes(r *gin.RouterGroup) {
// 需要登录 + 权限检查 + 操作日志 + 防重复(3 秒)
r.POST("/save",
authMiddleware.HeiCheckLogin(),
authMiddleware.HeiCheckPermission([]string{"sys:user:create"}),
log.SysLog("创建用户"),
authMiddleware.NoRepeat(3000),
h.UserSave,
)
// 只需要登录
r.GET("/info",
authMiddleware.HeiCheckLogin(),
h.GetUserInfo,
)
// 公开接口(无需认证)
r.GET("/public-info", h.PublicInfo)
}中间件执行顺序
在同一个请求中,中间件的执行顺序遵循先进后出原则(类似洋葱模型):
Request
│
▼
① Trace ───────────────────────── 生成 Trace ID
② AuthCheck ───────────────────── 路径认证检查
③ Recovery ────────────────────── panic 保护(defer)
④ CORS ────────────────────────── 跨域处理
⑤ HeiCheckLogin ───────────────── JWT 验证
⑥ HeiCheckPermission ──────────── 权限检查
⑦ SysLog ──────────────────────── 开始录制
⑧ NoRepeat ────────────────────── 防重复检查
│
▼
Handler ────────────────────────── 业务逻辑
│
▼
⑨ NoRepeat ────────────────────── 设置防重复标记
⑩ SysLog ──────────────────────── 完成录制(写入 DB)
⑪ HeiCheckPermission ──────────── 后处理
⑫ HeiCheckLogin ───────────────── 后处理
⑬ CORS ────────────────────────── 后处理
⑭ Recovery ────────────────────── 后处理(如有 panic)
⑮ AuthCheck ───────────────────── 后处理
⑯ Trace ───────────────────────── 后处理
│
▼
Response注意:中间件的"后处理"阶段通常不执行额外操作,核心逻辑在"前处理"阶段完成。Recovery 的 defer 在请求全过程中都有效。