2.9 KiB
2.9 KiB
4.8 横切机制
:::tip 概述 横切关注点不在业务代码中重复出现——认证、租户、日志、审计、软删分别由中间件链与 GORM 全局钩子在固定位置统一执行。本页给出"每个红线由谁执行"的总图。 :::
红线执行点总览
| 红线 | 执行点 | 时机 |
|---|---|---|
| 统一信封 + panic 恢复 | Response 中间件 | 响应写出时 |
| 身份认证 | JWT 中间件 | 请求进入业务前 |
| 租户上下文 | Tenant 中间件 + Scope | 请求级 + SQL 级 |
| 权限校验 | Authz 中间件(元数据驱动) | handler 前 |
| 操作日志 | OperationLog 中间件 | 请求结束后异步 |
| 限流 | RateLimit 中间件 | 认证前 |
| 审计字段盖章 | GORM create/update 钩子 | 写 SQL 前 |
| 物理删除拦截 | GORM delete 钩子 | 删除 SQL 前 |
| 软删过滤 | repository Scope(ApplyCtx) | 查询构建时 |
审计盖章(createStamp / updateStamp)
Insert 前:补 create_user / create_time / del_flag=0 / tenant_id(租户表)
Update 前:盖 update_user / update_time
业务代码永不手工赋值审计列——这是钩子存在的意义。create_user/update_user 从 ctx 身份取。
物理删除拦截(blockPhysicalDelete)
一切物理 DELETE 默认被拒绝。确需物理清理的场景(如 LogClean 任务清超期日志):
ctx = hooks.WithPhysicalDelete(ctx) // 显式放行,作用域仅此 ctx 链路
查询侧 Scope(ApplyCtx)
repository.Ctx(ctx) 在 SQL 构建前以 GORM Scope 注入:
所有表: del_flag = 0
租户白名单表: 非平台级身份追加 tenant_id IN (0, 自身租户)
租户判定依据 hooks.tenantTables 白名单(9 张表)——新增租户级表必须同步登记。
身份与上下文的流动
JWT 中间件 解析 Token → ctx 写入用户身份(loader 经 init 接线)
Tenant 中间件 加载租户 → ctx 写入租户身份
↓
service / repository / 钩子 从 ctx 读身份(盖章、隔离、日志)
ctx 是横切数据的唯一载体——不使用全局变量传递请求态数据。
日志的三个层次
| 层次 | 载体 | 内容 |
|---|---|---|
| 运行日志 | zap(log/ 目录) | 排查用,带 trace_id |
| 操作日志 | gin_operation_log 表 | 审计用,谁在何时对什么做了什么 |
| 登录日志 | gin_login_log 表 | 登录行为专项 |
操作日志的采集内容由 RouteSpec 声明驱动(Log/LogType),异步落库不阻塞响应。
演示模式(Demo 中间件)
app.demo=true 时写操作一律拒绝,读操作与登录类公开接口放行——演示环境保护数据的同时不影响体验。
横切的可裁剪性
WireCheck 保证接线缺失只降级不崩:去掉 auth 模块则身份扩展加载跳过,去掉 operation_log 则日志丢弃。裁剪部署形态由启动告警明确提示。