中间件注册后不生效需检查三类注册位置及handle()返回值:全局$middleware、分组$middlewaregroups、路由$routemiddleware;必须return $next($request)或明确响应,否则请求挂起。

中间件注册后不生效?检查 app/Http/Kernel.php 的注册位置
中间件只有被正确挂载到请求生命周期的某个“管道”里才会执行。Laravel 有三类注册位置:$middleware(全局)、$middlewareGroups(分组,如 web 或 api)、$routeMiddleware(路由级别)。常见错误是写好了中间件类,却只加在 $routeMiddleware 里,却在路由中忘记用 ->middleware() 调用;或者误把需要鉴权的中间件放在 $middleware 全局数组里,导致静态资源、健康检查接口也被拦截。
- 需要对所有 HTTP 请求统一处理(如日志、CORS)→ 放
$middleware - 仅限 Web 页面请求(带 session、CSRF)→ 必须绑定到
web组,且路由需属于该组(如通过Route::middleware('web')或使用Route::group(['middleware' => 'web'], ...)) - 只针对某几个 API 接口 → 注册到
$routeMiddleware,再在路由定义里显式调用,例如Route::get('/user', [UserController::class, 'index'])->middleware('auth.api')
handle() 方法里忘了调用 $next($request)?请求就卡死了
Laravel 中间件是洋葱模型:请求进来一层层进,响应出去一层层出。handle() 方法必须返回 $next($request) 的结果,否则后续中间件和控制器永远不会执行,浏览器会一直转圈或超时。这不是警告,是硬性要求——哪怕你只想做记录或重定向,也得明确控制流向。
- 想终止请求并跳转?用
return redirect()->to(...),不是redirect()->to(...)(少个return就静默失败) - 想返回 JSON 错误?用
return response()->json([...], 403) - 想放行?必须写
return $next($request),不能只写$next($request) - 调试时可在
handle()开头加Log::debug('middleware hit'),确认是否真被触发
自定义中间件传参?别用构造函数,用闭包或配置驱动
Laravel 中间件类的构造函数在应用启动时就被实例化(单例),无法接收路由参数或运行时值。比如你想让同一个权限中间件支持不同角色:->middleware('role:admin'),这时参数是通过字符串解析传进来的,不是构造函数注入的。
- 参数格式固定为
中间件名:参数1,参数2,在handle()方法第二个参数$next后,第三个参数就是字符串形式的参数(如'admin'或'admin,editor') - 不要在
__construct()里依赖Request或Auth,它们此时尚未可用 - 需要动态配置?改用配置文件(如
config/permissions.php)或服务容器绑定,而不是硬编码在中间件里 - 示例:在
handle($request, Closure $next, string $roles)中,用in_array(auth()->user()?->role, explode(',', $roles))判断
中间件顺序错了,auth 放 web 组后面?用户永远拿不到 session
中间件执行顺序直接影响变量可用性。比如 StartSession 和 AuthenticateSession 必须在 auth 前运行,否则 auth()->user() 永远是 null;同理,VerifyCsrfToken 必须在 StartSession 之后,否则 token 验证会失败。
- 打开
app/Http/Kernel.php,看$middlewareGroups['web']数组顺序:默认EncryptCookies→AddQueuedCookiesToResponse→StartSession→ShareErrorsFromSession→VerifyCsrfToken→SubstituteBindings - 如果你自定义中间件依赖 session 或 auth,请确保它排在这串之后;如果它要修改 cookie 或加密逻辑,则可能需要更靠前
- API 组(
api)默认不启用 session,所以auth:api走的是 token 或 passport,别指望它能读session()
handle() 里没写 return」这两点——前者导致逻辑不触发,后者导致整个请求挂起,连错误都不报。











