签入版本
This commit is contained in:
@@ -52,7 +52,7 @@
|
|||||||
▼
|
▼
|
||||||
┌──────────────┐
|
┌──────────────┐
|
||||||
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
||||||
│(log.operation)│ 写操作始终记录
|
│(log.operation)│ 写操作始终记录(#[WithoutOperationLog] 跳过)
|
||||||
└──────┬───────┘
|
└──────┬───────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
@@ -73,31 +73,19 @@
|
|||||||
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
||||||
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
||||||
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
||||||
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/middleware.php` → `auth_except` |
|
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/jwt.php` → `header_prefix` |
|
||||||
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
||||||
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库) | `config/middleware.php` → `log_except` |
|
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库,`#[WithoutOperationLog]` 跳过) | — |
|
||||||
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
||||||
|
|
||||||
## 排除配置
|
## 排除方式
|
||||||
|
|
||||||
```php
|
| 目标 | 机制 | 说明 |
|
||||||
// config/middleware.php
|
|------|------|------|
|
||||||
return [
|
| 认证(`auth.jwt`) | 路由分组 | 公开接口(`login`、`captcha`、`refresh`、`oauth2`)定义在认证组外,天然免认证 |
|
||||||
// Authenticate::handle() 命中时跳过 JWT 解析与权限校验(公开接口定义在路由组外,此为兜底)
|
| 操作日志(`log.operation`) | `#[WithoutOperationLog]` 注解 | 方法标注即不写入 `OperationLog`,优先级高于"写操作一律记录";适用于已有专门日志载体的接口,如登出记录写入登录日志(`login_log`,`log_type=2`) |
|
||||||
'auth_except' => [
|
|
||||||
'login',
|
操作日志排除机制详见 [4.2 请求处理链路](/zh/architecture/request-flow.html)。
|
||||||
'captcha',
|
|
||||||
'refresh',
|
|
||||||
],
|
|
||||||
// LogOperation::handle() 命中时不写入 OperationLog
|
|
||||||
// 登录/登出由 LoginLog 单独记录
|
|
||||||
'log_except' => [
|
|
||||||
'login',
|
|
||||||
'logout',
|
|
||||||
'captcha',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注入内容
|
## 注入内容
|
||||||
|
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
| 注解 | 目标 | 说明 | 读取方 |
|
| 注解 | 目标 | 说明 | 读取方 |
|
||||||
|------|------|------|--------|
|
|------|------|------|--------|
|
||||||
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
|
| `#[WithoutOperationLog]` | 方法 | 跳过操作日志标记(标注后写操作也不记录) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
||||||
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
||||||
|
|
||||||
@@ -383,6 +384,9 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
// 演示环境放行(允许在演示环境执行写操作)
|
// 演示环境放行(允许在演示环境执行写操作)
|
||||||
#[DemoAllow]
|
#[DemoAllow]
|
||||||
|
|
||||||
|
// 跳过操作日志(已有专门日志载体的写接口,如登出写入 login_log)
|
||||||
|
#[WithoutOperationLog]
|
||||||
|
|
||||||
// 组合使用
|
// 组合使用
|
||||||
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
||||||
#[Permission('sys:article:delete', '删除文章')]
|
#[Permission('sys:article:delete', '删除文章')]
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ public function terminate(Request $request, Response $response): void
|
|||||||
|
|
||||||
- `POST/PUT/DELETE/PATCH` 一律记录
|
- `POST/PUT/DELETE/PATCH` 一律记录
|
||||||
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
||||||
|
- 标注 `#[WithoutOperationLog]` 的方法一律不记录(优先级最高,如登出)
|
||||||
- 其它方法(OPTIONS/HEAD)不记录
|
- 其它方法(OPTIONS/HEAD)不记录
|
||||||
|
|
||||||
:::tip DemoMiddleware 说明
|
:::tip DemoMiddleware 说明
|
||||||
|
|||||||
@@ -216,11 +216,12 @@ if (! empty($attrs)) {
|
|||||||
|
|
||||||
## 白名单示例
|
## 白名单示例
|
||||||
|
|
||||||
当前代码中唯一标注 `#[DemoAllow]` 的方法:
|
当前代码中标注 `#[DemoAllow]` 的方法:
|
||||||
|
|
||||||
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
||||||
|--------|------|------|------|---------|
|
|--------|------|------|------|---------|
|
||||||
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
||||||
|
| `AuthController` | `logout` | `POST logout` | 用户登出 | 吊销当前令牌并写登录日志(`login_log`),不修改业务数据;演示环境必须允许退出 |
|
||||||
|
|
||||||
:::tip GET 路由天然放行
|
:::tip GET 路由天然放行
|
||||||
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ document/
|
|||||||
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
||||||
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
||||||
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
||||||
| `config/middleware.php` | 受信代理等中间件配置 |
|
| `config/app.php` | 应用配置(名称 / 时区 / 调试模式、受信代理 `trusted_proxies`) |
|
||||||
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
||||||
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
||||||
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ GENERATOR_APP_NAME=tool # 应用名(路由前缀、前端目录
|
|||||||
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
||||||
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
||||||
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
||||||
| `TRUSTED_PROXIES` | `config/middleware.php` ★ | 受信代理 |
|
| `TRUSTED_PROXIES` | `config/app.php` | 受信代理 |
|
||||||
| `LOG_*` | `config/logging.php` | 日志 |
|
| `LOG_*` | `config/logging.php` | 日志 |
|
||||||
| `MAIL_*` | `config/mail.php` | 邮件 |
|
| `MAIL_*` | `config/mail.php` | 邮件 |
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
▼
|
▼
|
||||||
┌──────────────┐
|
┌──────────────┐
|
||||||
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
||||||
│(log.operation)│ 写操作始终记录
|
│(log.operation)│ 写操作始终记录(#[WithoutOperationLog] 跳过)
|
||||||
└──────┬───────┘
|
└──────┬───────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
@@ -73,31 +73,19 @@
|
|||||||
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
||||||
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
||||||
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
||||||
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/middleware.php` → `auth_except` |
|
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/jwt.php` → `header_prefix` |
|
||||||
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
||||||
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库) | `config/middleware.php` → `log_except` |
|
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库,`#[WithoutOperationLog]` 跳过) | — |
|
||||||
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
||||||
|
|
||||||
## 排除配置
|
## 排除方式
|
||||||
|
|
||||||
```php
|
| 目标 | 机制 | 说明 |
|
||||||
// config/middleware.php
|
|------|------|------|
|
||||||
return [
|
| 认证(`auth.jwt`) | 路由分组 | 公开接口(`login`、`captcha`、`refresh`、`oauth2`)定义在认证组外,天然免认证 |
|
||||||
// Authenticate::handle() 命中时跳过 JWT 解析与权限校验(公开接口定义在路由组外,此为兜底)
|
| 操作日志(`log.operation`) | `#[WithoutOperationLog]` 注解 | 方法标注即不写入 `OperationLog`,优先级高于"写操作一律记录";适用于已有专门日志载体的接口,如登出记录写入登录日志(`login_log`,`log_type=2`) |
|
||||||
'auth_except' => [
|
|
||||||
'login',
|
操作日志排除机制详见 [4.2 请求处理链路](/zh/architecture/request-flow.html)。
|
||||||
'captcha',
|
|
||||||
'refresh',
|
|
||||||
],
|
|
||||||
// LogOperation::handle() 命中时不写入 OperationLog
|
|
||||||
// 登录/登出由 LoginLog 单独记录
|
|
||||||
'log_except' => [
|
|
||||||
'login',
|
|
||||||
'logout',
|
|
||||||
'captcha',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注入内容
|
## 注入内容
|
||||||
|
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
| 注解 | 目标 | 说明 | 读取方 |
|
| 注解 | 目标 | 说明 | 读取方 |
|
||||||
|------|------|------|--------|
|
|------|------|------|--------|
|
||||||
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
|
| `#[WithoutOperationLog]` | 方法 | 跳过操作日志标记(标注后写操作也不记录) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
||||||
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
||||||
|
|
||||||
@@ -383,6 +384,9 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
// 演示环境放行(允许在演示环境执行写操作)
|
// 演示环境放行(允许在演示环境执行写操作)
|
||||||
#[DemoAllow]
|
#[DemoAllow]
|
||||||
|
|
||||||
|
// 跳过操作日志(已有专门日志载体的写接口,如登出写入 login_log)
|
||||||
|
#[WithoutOperationLog]
|
||||||
|
|
||||||
// 组合使用
|
// 组合使用
|
||||||
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
||||||
#[Permission('sys:article:delete', '删除文章')]
|
#[Permission('sys:article:delete', '删除文章')]
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ public function terminate(Request $request, Response $response): void
|
|||||||
|
|
||||||
- `POST/PUT/DELETE/PATCH` 一律记录
|
- `POST/PUT/DELETE/PATCH` 一律记录
|
||||||
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
||||||
|
- 标注 `#[WithoutOperationLog]` 的方法一律不记录(优先级最高,如登出)
|
||||||
- 其它方法(OPTIONS/HEAD)不记录
|
- 其它方法(OPTIONS/HEAD)不记录
|
||||||
|
|
||||||
:::tip DemoMiddleware 说明
|
:::tip DemoMiddleware 说明
|
||||||
|
|||||||
@@ -216,11 +216,12 @@ if (! empty($attrs)) {
|
|||||||
|
|
||||||
## 白名单示例
|
## 白名单示例
|
||||||
|
|
||||||
当前代码中唯一标注 `#[DemoAllow]` 的方法:
|
当前代码中标注 `#[DemoAllow]` 的方法:
|
||||||
|
|
||||||
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
||||||
|--------|------|------|------|---------|
|
|--------|------|------|------|---------|
|
||||||
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
||||||
|
| `AuthController` | `logout` | `POST logout` | 用户登出 | 吊销当前令牌并写登录日志(`login_log`),不修改业务数据;演示环境必须允许退出 |
|
||||||
|
|
||||||
:::tip GET 路由天然放行
|
:::tip GET 路由天然放行
|
||||||
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ document/
|
|||||||
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
||||||
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
||||||
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
||||||
| `config/middleware.php` | 受信代理等中间件配置 |
|
| `config/app.php` | 应用配置(名称 / 时区 / 调试模式、受信代理 `trusted_proxies`) |
|
||||||
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
||||||
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
||||||
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ GENERATOR_APP_NAME=tool # 应用名(路由前缀、前端目录
|
|||||||
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
||||||
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
||||||
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
||||||
| `TRUSTED_PROXIES` | `config/middleware.php` ★ | 受信代理 |
|
| `TRUSTED_PROXIES` | `config/app.php` | 受信代理 |
|
||||||
| `LOG_*` | `config/logging.php` | 日志 |
|
| `LOG_*` | `config/logging.php` | 日志 |
|
||||||
| `MAIL_*` | `config/mail.php` | 邮件 |
|
| `MAIL_*` | `config/mail.php` | 邮件 |
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
▼
|
▼
|
||||||
┌──────────────┐
|
┌──────────────┐
|
||||||
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
│ LogOperation │ 记录操作日志(terminable,响应后写入)
|
||||||
│(log.operation)│ 写操作始终记录
|
│(log.operation)│ 写操作始终记录(#[WithoutOperationLog] 跳过)
|
||||||
└──────┬───────┘
|
└──────┬───────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
@@ -73,31 +73,19 @@
|
|||||||
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
| ProxyMiddleware | API 组前置 | 代理头解析,提取真实客户端 IP | `.env` → `TRUSTED_PROXIES` |
|
||||||
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
| Cors | API 组前置 | 跨域处理(OPTIONS 预检 + 响应头) | `config/cors.php` → `CORS_ALLOW_ORIGIN` |
|
||||||
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
| ForceJsonResponse | API 组前置 | 强制 `Content-Type: application/json` | — |
|
||||||
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/middleware.php` → `auth_except` |
|
| Authenticate | 路由组(别名 `auth.jwt`) | JWT 认证 + 权限校验(`#[Permission]` 注解) | `config/jwt.php` → `header_prefix` |
|
||||||
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
| ResolveTenant | 路由组(别名 `tenant`) | 租户上下文注入与校验 | 超管(uid=1)跳过校验 |
|
||||||
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库) | `config/middleware.php` → `log_except` |
|
| LogOperation | 路由组(别名 `log.operation`) | 操作日志记录(terminable,响应后落库,`#[WithoutOperationLog]` 跳过) | — |
|
||||||
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
| DemoMiddleware | 路由组(别名 `demo`,tenant 与 log.operation 之间) | 演示模式拦截写操作(无 `#[DemoAllow]` 的写操作返回 403) | `config('app.demo_mode')` |
|
||||||
|
|
||||||
## 排除配置
|
## 排除方式
|
||||||
|
|
||||||
```php
|
| 目标 | 机制 | 说明 |
|
||||||
// config/middleware.php
|
|------|------|------|
|
||||||
return [
|
| 认证(`auth.jwt`) | 路由分组 | 公开接口(`login`、`captcha`、`refresh`、`oauth2`)定义在认证组外,天然免认证 |
|
||||||
// Authenticate::handle() 命中时跳过 JWT 解析与权限校验(公开接口定义在路由组外,此为兜底)
|
| 操作日志(`log.operation`) | `#[WithoutOperationLog]` 注解 | 方法标注即不写入 `OperationLog`,优先级高于"写操作一律记录";适用于已有专门日志载体的接口,如登出记录写入登录日志(`login_log`,`log_type=2`) |
|
||||||
'auth_except' => [
|
|
||||||
'login',
|
操作日志排除机制详见 [4.2 请求处理链路](/zh/architecture/request-flow.html)。
|
||||||
'captcha',
|
|
||||||
'refresh',
|
|
||||||
],
|
|
||||||
// LogOperation::handle() 命中时不写入 OperationLog
|
|
||||||
// 登录/登出由 LoginLog 单独记录
|
|
||||||
'log_except' => [
|
|
||||||
'login',
|
|
||||||
'logout',
|
|
||||||
'captcha',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注入内容
|
## 注入内容
|
||||||
|
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
| 注解 | 目标 | 说明 | 读取方 |
|
| 注解 | 目标 | 说明 | 读取方 |
|
||||||
|------|------|------|--------|
|
|------|------|------|--------|
|
||||||
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
| `#[OperationLog]` | 方法 | 操作日志(标题、类型、描述模板) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
|
| `#[WithoutOperationLog]` | 方法 | 跳过操作日志标记(标注后写操作也不记录) | `LogOperation` 中间件(ReflectionMethod) |
|
||||||
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
| `#[Permission]` | 方法 | 权限校验(权限编码、名称) | `Authenticate` 中间件(ReflectionMethod) |
|
||||||
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
| `#[DemoAllow]` | 方法 | 演示环境放行标记 | `DemoMiddleware`(ReflectionMethod) |
|
||||||
|
|
||||||
@@ -383,6 +384,9 @@ Route::middleware(['auth.jwt', 'tenant', 'demo', 'log.operation'])->group(functi
|
|||||||
// 演示环境放行(允许在演示环境执行写操作)
|
// 演示环境放行(允许在演示环境执行写操作)
|
||||||
#[DemoAllow]
|
#[DemoAllow]
|
||||||
|
|
||||||
|
// 跳过操作日志(已有专门日志载体的写接口,如登出写入 login_log)
|
||||||
|
#[WithoutOperationLog]
|
||||||
|
|
||||||
// 组合使用
|
// 组合使用
|
||||||
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
#[OperationLog('文章管理-删除', OperationLog::TYPE_DELETE, '删除文章ID:{id}')]
|
||||||
#[Permission('sys:article:delete', '删除文章')]
|
#[Permission('sys:article:delete', '删除文章')]
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ public function terminate(Request $request, Response $response): void
|
|||||||
|
|
||||||
- `POST/PUT/DELETE/PATCH` 一律记录
|
- `POST/PUT/DELETE/PATCH` 一律记录
|
||||||
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
- `GET` 仅在注解类型为 `EXPORT / DOWNLOAD / IMPORT` 时记录
|
||||||
|
- 标注 `#[WithoutOperationLog]` 的方法一律不记录(优先级最高,如登出)
|
||||||
- 其它方法(OPTIONS/HEAD)不记录
|
- 其它方法(OPTIONS/HEAD)不记录
|
||||||
|
|
||||||
:::tip DemoMiddleware 说明
|
:::tip DemoMiddleware 说明
|
||||||
|
|||||||
@@ -216,11 +216,12 @@ if (! empty($attrs)) {
|
|||||||
|
|
||||||
## 白名单示例
|
## 白名单示例
|
||||||
|
|
||||||
当前代码中唯一标注 `#[DemoAllow]` 的方法:
|
当前代码中标注 `#[DemoAllow]` 的方法:
|
||||||
|
|
||||||
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
| 控制器 | 方法 | 路由 | 说明 | 放行理由 |
|
||||||
|--------|------|------|------|---------|
|
|--------|------|------|------|---------|
|
||||||
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
| `GeneratorController` | `preview` | `GET generator/preview` | 代码生成预览 | 仅预览不写盘,不修改业务数据 |
|
||||||
|
| `AuthController` | `logout` | `POST logout` | 用户登出 | 吊销当前令牌并写登录日志(`login_log`),不修改业务数据;演示环境必须允许退出 |
|
||||||
|
|
||||||
:::tip GET 路由天然放行
|
:::tip GET 路由天然放行
|
||||||
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
`dict/refreshCache` 等维护接口均为 GET 方法,本就不受拦截、无需注解。`#[DemoAllow]` 的价值在于**防御性兜底**——即使后续将路由方法改为 POST,演示模式下仍可正常访问。
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ document/
|
|||||||
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
| `config/jwt.php` | JWT 配置(密钥 / access·refresh 有效期 / 签发者) |
|
||||||
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
| `config/file.php` | 文件上传配置(目录 / 域名 / 大小 / 后缀白名单) |
|
||||||
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
| `config/cors.php` | 跨域配置(允许来源 / 方法 / 头) |
|
||||||
| `config/middleware.php` | 受信代理等中间件配置 |
|
| `config/app.php` | 应用配置(名称 / 时区 / 调试模式、受信代理 `trusted_proxies`) |
|
||||||
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
| `config/api.php` | 响应驼峰/下划线自动转换开关 |
|
||||||
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
| `config/tenant.php` | 多租户配置(默认租户 ID) |
|
||||||
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
| `config/generator.php` | 代码生成器配置(父菜单 ID、应用名) |
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ GENERATOR_APP_NAME=tool # 应用名(路由前缀、前端目录
|
|||||||
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
| `CAPTCHA_*` | `config/captcha.php` ★ | 验证码 |
|
||||||
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
| `DEFAULT_TENANT_ID` | `config/tenant.php` ★ | 多租户 |
|
||||||
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
| `GENERATOR_*` | `config/generator.php` | 代码生成器 |
|
||||||
| `TRUSTED_PROXIES` | `config/middleware.php` ★ | 受信代理 |
|
| `TRUSTED_PROXIES` | `config/app.php` | 受信代理 |
|
||||||
| `LOG_*` | `config/logging.php` | 日志 |
|
| `LOG_*` | `config/logging.php` | 日志 |
|
||||||
| `MAIL_*` | `config/mail.php` | 邮件 |
|
| `MAIL_*` | `config/mail.php` | 邮件 |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user