hyperf 3.1 中间件执行顺序为:控制器构造函数绑定的中间件最晚执行,其次为路由级中间件,最后是全局中间件(按 config/autoload/middlewares.php 中数组顺序从左到右执行);authmiddleware 必须排在 validationmiddleware 前以避免绕过鉴权;中间件短路必须显式 return responseinterface,禁止使用 exit/die。

Hyperf 3.1 中间件执行顺序直接影响请求能否被正确拦截、鉴权或修改,顺序错一位就可能导致 JWT 校验失效、日志漏记、甚至绕过权限检查。
中间件注册位置决定全局执行顺序
打开 config/autoload/middlewares.php 文件,找到 'http' => [] 数组。
数组内中间件的声明顺序就是它们在请求生命周期中的执行顺序——从左到右,先注册的先执行。
例如:['App\Middleware\AuthMiddleware', 'App\Middleware\LoggingMiddleware', 'Hyperf\Validation\Middleware\ValidationMiddleware'] 表示 Auth → Logging → Validation。
【AuthMiddleware 必须排在 ValidationMiddleware 前面】,否则未登录用户可能直接触发参数校验并返回 422,绕过了身份验证环节。
路由级中间件优先于全局中间件
全局中间件对所有 HTTP 请求生效,但路由级中间件会插入到全局链路中更靠前的位置。
在定义路由时使用 ->middleware() 链式调用:
Router::get('/admin/users', [UserController::class, 'index'])->middleware(AuthAdminMiddleware::class);
此时执行顺序为:AuthAdminMiddleware → 全局中间件列表(按注册顺序)。
注意:同一个中间件若既注册在全局又绑定到某条路由,它会执行两次——除非你在中间件内部做了协程上下文去重判断。
控制器构造函数中绑定的中间件最晚执行
在控制器构造函数中调用 $this->middleware() 绑定的中间件,会在所有全局和路由级中间件之后运行。
第一步:在控制器类中添加构造函数:
public function __construct() { $this->middleware(PermissionCheckMiddleware::class)->only(['delete']); }
第二步:该中间件仅对 delete 方法生效,且在请求进入 action 前最后一刻才执行。
这适合做细粒度操作级权限控制,比如“删除订单需额外校验订单状态”,但不能替代前置鉴权——因为此时请求已通过 Auth 和 Validation,若此处拒绝,响应状态码可能不符合 REST 规范(应是 403 而非 401)。
中间件内部的短路逻辑必须显式 return
Hyperf 中间件遵循 PSR-15 规范,process() 方法必须返回 ResponseInterface 才能中断后续流程。
方法一:直接返回响应对象(短路)
if (!$token) { return $response->json(['code' => 401, 'msg' => 'Unauthorized']); }
方法二:继续调用 handler(放行)
return $handler->handle($request);
⚠️ 错误写法:echo json_encode([...]); exit; 或 die(); —— 这会终止整个协程,导致连接异常关闭、日志截断、内存泄漏。











