文档目录
中间件管道

简介

本技术文档围绕 DouPHP 的中间件管道系统,系统性说明请求从路由解析到控制器执行的完整流程,解释全局、路由级与条件中间件的组合机制;深入剖析后台与 API 端内置中间件(安全头、认证、权限、CSRF、限流等)的实现要点;提供自定义中间件开发规范、依赖注入与错误处理最佳实践;并给出性能优化与调试技巧。面向初学者解释“什么是中间件、为什么需要中间件”,同时为高级开发者提供管道定制与扩展指南。

项目结构

DouPHP 将中间件能力抽象在核心框架中,并通过各端(后台 admin、API、前台 front)以“别名 + 默认栈 + 路由覆盖”的方式组织:

  • 核心分发器负责在中间件管道中执行控制器方法。
  • 后端 Resolver 定义后台默认中间件栈与别名映射。
  • API Resolver 定义 API 默认中间件栈与别名映射,并结合配置决定是否启用用户认证中间件。
  • 各端 middleware 目录包含具体中间件实现。
  • API 鉴权模式通过 api/init/middleware.php 集中声明,供 UserAuthMiddleware 决策。
graph TB
subgraph "核心"
D["Dispatcher<br/>运行中间件管道"]
MR["MiddlewarePipeline<br/>核心框架"]
end
subgraph "后台 Admin"
AR["AdminResolver<br/>默认栈: security_headers, trust_proxy, auth, permission, csrf, workspace"]
AM_Auth["AuthMiddleware"]
AM_Permission["PermissionMiddleware"]
AM_Csrf["CsrfMiddleware"]
AM_Sec["SecurityHeadersMiddleware"]
AM_Workspace["AdminWorkspaceMiddleware"]
end
subgraph "API"
ARes["ApiResolver<br/>默认栈: security_headers, trust_proxy, throttle[, user_auth]"]
AU_Auth["UserAuthMiddleware"]
AU_Throttle["ThrottleMiddleware"]
AU_Sec["SecurityHeadersMiddleware"]
AuthCfg["api/init/middleware.php<br/>auth_modes / work_required"]
end
D --> MR
AR --> AM_Sec
AR --> AM_Auth
AR --> AM_Permission
AR --> AM_Csrf
AR --> AM_Workspace
ARes --> AU_Sec
ARes --> AU_Throttle
ARes --> AU_Auth
AU_Auth --> AuthCfg

图表来源

  • Dispatcher.php:41-58
  • AdminResolver.php:44-63
  • ApiResolver.php:41-51
  • middleware.php:33-146

章节来源

  • Dispatcher.php:41-58
  • AdminResolver.php:44-63
  • ApiResolver.php:41-51
  • middleware.php:33-146

核心组件

  • 中央分发器 Dispatcher:接收路由解析结果,设置 Request 路由参数后,通过 MiddlewarePipeline 执行中间件链,最终调用控制器方法。
  • 后台 Resolver AdminResolver:维护后台默认中间件栈与别名映射,结合命中条目生成 DispatchPlan。
  • API Resolver ApiResolver:维护 API 默认中间件栈与别名映射,依据 features.user 决定是否加入用户认证中间件。
  • 中间件实现:
    • 后台:安全头、信任代理、登录认证、模块权限、CSRF、工作台变量注入。
    • API:安全头、信任代理、限流、用户认证(基于配置的模式)。

章节来源

  • Dispatcher.php:41-58
  • AdminResolver.php:44-63
  • ApiResolver.php:41-51
  • AuthMiddleware.php:24-50
  • PermissionMiddleware.php:25-70
  • CsrfMiddleware.php:24-80
  • SecurityHeadersMiddleware.php:23-28
  • AdminWorkspaceMiddleware.php:26-83
  • UserAuthMiddleware.php:25-42
  • ThrottleMiddleware.php:25-90
  • SecurityHeadersMiddleware.php:23-28

架构总览

请求进入后,由对应端的 Resolver 解析路由并产出 DispatchPlan,随后交由 Dispatcher 在中间件管道中执行。每个中间件可读取/修改 Request、拦截响应或抛出异常中断管道。

sequenceDiagram
participant Client as "客户端"
participant Resolver as "端侧 Resolver"
participant Dispatcher as "Dispatcher"
participant Pipeline as "MiddlewarePipeline"
participant MW as "中间件链"
participant Controller as "控制器"
Client->>Resolver : 发起请求
Resolver-->>Dispatcher : DispatchPlan(控制器FQCN/方法/参数/中间件列表)
Dispatcher->>Dispatcher : 写入Request路由参数
Dispatcher->>Pipeline : run(回调=实例化并调用控制器)
Pipeline->>MW : 依次执行handle(next)
MW-->>Pipeline : 放行或返回响应/抛异常
Pipeline->>Controller : 调用控制器方法
Controller-->>Pipeline : 返回结果
Pipeline-->>Dispatcher : 返回结果
Dispatcher-->>Client : 输出响应

图表来源

  • Dispatcher.php:41-58
  • AdminResolver.php:72-103
  • ApiResolver.php:60-90

详细组件分析

后台中间件栈与执行顺序

后台默认栈顺序为:安全头 → 信任代理 → 登录认证 → 模块权限 → CSRF → 工作台变量注入。该顺序确保:

  • 先设置安全响应头与可信代理信息。
  • 再校验管理员登录态与模块访问权限。
  • 然后进行表单提交 CSRF 校验。
  • 最后向视图注入全局工作区数据。
flowchart TD
Start(["请求进入后台"]) --> Sec["安全响应头"]
Sec --> Proxy["信任代理"]
Proxy --> Auth["管理员登录态恢复"]
Auth --> |未登录| RedirectLogin["重定向到登录页"]
Auth --> Perm["模块权限检查"]
Perm --> |无权限| RedirectHome["重定向到管理首页"]
Perm --> Csrf["CSRF令牌校验"]
Csrf --> Workspace["注入global_admin/workspace/unum"]
Workspace --> End(["到达控制器"])

图表来源

  • AdminResolver.php:44-63
  • AuthMiddleware.php:42-50
  • PermissionMiddleware.php:49-70
  • CsrfMiddleware.php:47-80
  • AdminWorkspaceMiddleware.php:58-83

章节来源

  • AdminResolver.php:44-63
  • AuthMiddleware.php:24-50
  • PermissionMiddleware.php:25-70
  • CsrfMiddleware.php:24-80
  • AdminWorkspaceMiddleware.php:26-83

API 中间件栈与执行顺序

API 默认栈为:安全头 → 信任代理 → 限流 →(可选)用户认证。用户认证是否进入默认栈取决于 features.user 配置。UserAuthMiddleware 根据 api/init/middleware.php 中的 auth_modes 与 work_required 对每个路由段进行三态决策(public/optional/required),并在必要时叠加工作端身份校验。

flowchart TD
AStart(["请求进入API"]) --> ASec["安全响应头"]
ASec --> AProxy["信任代理"]
AProxy --> AThrottle["按路由配额限流"]
AThrottle --> |超限| AR429["返回429并终止"]
AThrottle --> AAuth{"是否启用用户认证?"}
AAuth --> |否| AController["控制器"]
AAuth --> |是| AMode["按auth_modes判定public/optional/required"]
AMode --> |public| AController
AMode --> |optional| ACheck["尝试解析登录态"]
ACheck --> AController
AMode --> |required| ARequire["必须登录"]
ARequire --> |失败| A401["返回401并终止"]
ARequire --> |成功| AWork{"是否work_required?"}
AWork --> |是| AWorkCheck["校验工作端身份"]
AWorkCheck --> |失败| A403["返回403并终止"]
AWorkCheck --> AController
AWork --> |否| AController

图表来源

  • ApiResolver.php:41-51
  • ApiResolver.php:100-107
  • UserAuthMiddleware.php:25-42
  • ThrottleMiddleware.php:33-90
  • middleware.php:33-146

章节来源

  • ApiResolver.php:41-51
  • ApiResolver.php:100-107
  • UserAuthMiddleware.php:25-42
  • ThrottleMiddleware.php:33-90
  • middleware.php:33-146

关键中间件职责与行为

后台登录认证中间件(AuthMiddleware)

  • 职责:从会话恢复管理员登录态;未登录时抛出响应异常并重定向到登录页。
  • 设计要点:免登入口通过路由级 withoutMiddleware 声明式豁免,不在中间件内硬编码名单。

章节来源

  • AuthMiddleware.php:24-50

后台权限中间件(PermissionMiddleware)

  • 职责:校验当前管理员对当前模块/动作的访问权限;超级管理员直接放行;否则按白名单判定。
  • 依赖:前置 AuthMiddleware 已注入登录管理员上下文。

章节来源

  • PermissionMiddleware.php:25-70

后台CSRF中间件(CsrfMiddleware)

  • 职责:校验后台表单提交的CSRF令牌;支持例外令牌与GET续跑链接场景;失败时抛出领域异常并由后台统一提示。
  • 设计要点:完全豁免的路由通过路由级 withoutMiddleware 声明式豁免。

章节来源

  • CsrfMiddleware.php:24-80

后台安全头中间件(SecurityHeadersMiddleware)

  • 职责:薄壳继承基类,统一设置安全响应头。

章节来源

  • SecurityHeadersMiddleware.php:23-28

后台工作台变量注入中间件(AdminWorkspaceMiddleware)

  • 职责:在已通过认证与权限的请求中,向视图引擎注入 global_admin、workspace、unum 等变量。
  • 设计要点:位于认证与权限之后,避免对登录页或越权重定向执行额外逻辑。

章节来源

  • AdminWorkspaceMiddleware.php:26-83

API限流中间件(ThrottleMiddleware)

  • 职责:对敏感与公共写接口按 IP 限流;超限返回 JSON 429 并附带 Retry-After。
  • 设计要点:通过路由键匹配配额表,拒绝时立即终止。

章节来源

  • ThrottleMiddleware.php:25-90

API安全头中间件(SecurityHeadersMiddleware)

  • 职责:薄壳继承基类,统一设置安全响应头。

章节来源

  • SecurityHeadersMiddleware.php:23-28

API用户认证中间件(UserAuthMiddleware)

  • 职责:从 Authorization 头提取 Bearer token,交给 auth('api') guard 解析登录态;拒绝时返回 JSON 错误并终止。
  • 配置驱动:auth_modes 与 work_required 在 api/init/middleware.php 中集中声明,决定每路由的鉴权级别与工作端策略。

章节来源

  • UserAuthMiddleware.php:25-42
  • middleware.php:33-146

管道执行序列(后台示例)

sequenceDiagram
participant R as "AdminResolver"
participant D as "Dispatcher"
participant P as "MiddlewarePipeline"
participant M1 as "SecurityHeaders"
participant M2 as "TrustProxy"
participant M3 as "Auth"
participant M4 as "Permission"
participant M5 as "Csrf"
participant M6 as "Workspace"
participant C as "控制器"
R-->>D : DispatchPlan(含中间件别名列表)
D->>P : run(回调=实例化控制器)
P->>M1 : handle(next)
M1->>M2 : next()
M2->>M3 : next()
M3->>M3 : 恢复登录态
alt 未登录
M3-->>P : 抛出响应异常(重定向登录)
else 已登录
M3->>M4 : next()
M4->>M4 : 校验模块权限
alt 无权限
M4-->>P : 抛出响应异常(重定向首页)
else 有权限
M4->>M5 : next()
M5->>M5 : 校验CSRF
alt 校验失败
M5-->>P : 抛出领域异常(统一提示)
else 通过
M5->>M6 : next()
M6->>M6 : 注入全局视图变量
M6->>C : 调用控制器
C-->>P : 返回结果
P-->>D : 返回结果
end
end
end

图表来源

  • AdminResolver.php:44-63
  • Dispatcher.php:41-58
  • AuthMiddleware.php:42-50
  • PermissionMiddleware.php:49-70
  • CsrfMiddleware.php:47-80
  • AdminWorkspaceMiddleware.php:58-83

依赖关系分析

  • 分发器依赖核心中间件管道与容器,用于懒实例化控制器与方法调用。
  • 后台 Resolver 依赖中间件注册表与别名映射,组合默认栈与路由级覆盖。
  • API Resolver 依赖配置开关(features.user)动态决定是否加入用户认证中间件。
  • 各中间件之间通过 next 回调串联,形成严格的执行顺序与短路能力。
graph LR
D["Dispatcher"] --> MP["MiddlewarePipeline"]
AR["AdminResolver"] --> MR["MiddlewareRegistry"]
ARes["ApiResolver"] --> MR
MR --> Aliases["别名映射"]
Aliases --> AMW["后台中间件集合"]
Aliases --> AIMW["API中间件集合"]

图表来源

  • Dispatcher.php:41-58
  • AdminResolver.php:44-63
  • ApiResolver.php:41-51

章节来源

  • Dispatcher.php:41-58
  • AdminResolver.php:44-63
  • ApiResolver.php:41-51

性能考虑

  • 中间件顺序影响性能:将轻量且必要的中间件(如安全头、信任代理)置于前端,尽早设置响应头与上下文;将昂贵操作(如权限计算、CSRF校验)放在必要路径上。
  • 条件启用:API 端根据 features.user 决定是否加载用户认证中间件,减少不必要开销。
  • 短路机制:认证失败、权限不足、CSRF失败、限流超限均快速返回响应,避免后续控制器执行。
  • 视图变量注入仅在已通过认证与权限的请求中进行,避免对登录页或重定向路径产生额外负载。

故障排查指南

  • 后台登录失败或频繁跳转登录页:检查 AuthMiddleware 的会话恢复逻辑与路由级 withoutMiddleware 是否正确豁免登录相关入口。
  • 权限不足被重定向到管理首页:确认 PermissionMiddleware 的模块/动作判定逻辑与管理员类型。
  • CSRF 校验失败提示页面过期:核对 CsrfMiddleware 的令牌模型与例外路由配置,以及表单渲染与提交字段是否正确。
  • API 429 限流:查看 ThrottleMiddleware 的路由配额表与窗口时间,必要时调整配额或放宽限制。
  • API 401/403 认证失败:检查 api/init/middleware.php 的 auth_modes 与 work_required 配置是否与路由一致,并确保 Authorization 头携带正确 token。

章节来源

  • AuthMiddleware.php:42-50
  • PermissionMiddleware.php:49-70
  • CsrfMiddleware.php:47-80
  • ThrottleMiddleware.php:64-90
  • middleware.php:33-146

结论

DouPHP 的中间件管道通过“核心分发器 + 端侧 Resolver + 中间件别名与默认栈”的组合,实现了清晰的分层与可扩展的请求处理流程。后台与 API 端分别提供了安全、认证、权限、CSRF、限流等关键中间件,并以配置驱动的方式灵活组合。遵循本文档的规范与实践,可以高效地开发自定义中间件、优化管道性能,并保障系统的安全性与可维护性。

附录

自定义中间件开发规范

  • 接口契约:实现核心框架定义的中间件接口,提供 handle($next) 方法,负责在 next() 前后执行横切逻辑。
  • 依赖注入:通过构造函数注入所需服务(如权限门、工作区构建器等),保持单一职责与可测试性。
  • 错误处理:使用框架异常或响应对象中断管道(如 HttpResponseException、DomainException、ApiResponse),避免吞掉异常。
  • 配置驱动:将易变策略(如鉴权模式、限流配额)外置到配置文件,便于管理与灰度。

章节来源

  • PermissionMiddleware.php:34-43
  • AdminWorkspaceMiddleware.php:38-52
  • UserAuthMiddleware.php:25-42
  • ThrottleMiddleware.php:33-90

中间件注册与管理机制

  • 全局中间件:在各端 Resolver 的默认别名栈中声明,所有请求都会经过。
  • 路由中间件:通过路由命中条目携带的 middleware/withoutMiddleware 参数进行叠加或豁免。
  • 条件中间件:根据配置(如 features.user)动态决定是否加入默认栈。

章节来源

  • AdminResolver.php:44-63
  • ApiResolver.php:41-51
  • ApiResolver.php:100-107

最佳实践

  • 明确中间件职责边界:认证、权限、CSRF、限流、安全头等各司其职,避免在一个中间件中做过多事情。
  • 优先短路:在早期阶段判断并返回响应,减少后续不必要的处理。
  • 可观测性:在关键中间件记录日志(如限流拒绝、认证失败),便于问题定位。
  • 可配置化:将策略与阈值放入配置,便于不同环境差异化部署。
添加日期:2026-10-05