0

0

Laravel的中间件(Middleware)是如何实现请求过滤的? (全局与路由中间件)

穿越時空

穿越時空

发布时间:2026-01-13 04:25:29

|

293人浏览过

|

来源于php中文网

原创

Laravel中间件执行顺序由注册位置决定,构成嵌套闭包链:越早注册越靠近外层,越早拦截请求、越晚处理响应;全局中间件包裹整个应用,路由中间件需显式绑定,数组顺序即执行顺序,且必须调用$next($request)才能继续链式执行。

laravel的中间件(middleware)是如何实现请求过滤的? (全局与路由中间件)

中间件的执行顺序由 $middleware$middlewareGroups路由定义共同决定

Laravel 不是按“全局 > 路由组 > 单个路由”线性叠加执行,而是把所有中间件构造成一个嵌套闭包链(类似俄罗斯套娃)。每次 next($request) 调用,实际是进入下一层中间件。所以顺序取决于你往链里“塞”的位置——越早注册的中间件,越靠近外层,也就越早拦截请求、越晚看到响应。

关键点:

  • $middleware(在 app/Http/Kernel.php)里的中间件会包裹整个应用,包括 Artisan 命令和非 HTTP 请求(如队列监听器触发的 HTTP 请求),但不包含 CLI 命令本身
  • $middlewareGroups 中的 webapi 是命名分组,必须显式通过 ->middleware('web')Route::middleware('api') 应用,不会自动生效
  • 路由上直接调用 ->middleware(XXX) 时,该中间件会被插入到对应分组之后、控制器执行之前
  • 多个中间件同时绑定时,数组顺序即执行顺序:->middleware([First::class, Second::class]) 表示 First 先执行

handle() 方法中忘记调用 $next($request) 就会中断请求链

这是最常踩的坑:中间件不是“过滤器”,而是“拦截器 + 转发器”。如果你在 handle() 里做了权限判断后直接 return response()->json(...),那后续所有中间件和控制器都不会执行——这没错,但容易误以为“只是跳过”,其实整个链已终止。

正确做法是明确区分“放行”和“拦截”:

public function handle($request, Closure $next)
{
    if (! $request->user() || ! $request->user()->hasRole('admin')) {
        return response()->json(['error' => 'Unauthorized'], 403);
    }

    // ✅ 必须调用 $next 才能继续往下走
    return $next($request);
}

漏掉 return $next($request) 的后果是:控制器永远收不到请求,且无报错,只有空白响应或超时。

全局中间件和路由中间件对 sessioncsrf 等依赖有隐式顺序要求

比如 StartSession 必须在 VerifyCsrfToken 之前运行,否则 CSRF token 读不到 session;而 EncryptCookies 又必须在 StartSession 之前,否则无法解密 session cookie。这些依赖关系不是靠文档记住的,而是看 $middleware 数组的书写顺序。

Prisms AI
Prisms AI

无代码构建AI应用的平台

下载

Laravel 默认顺序已经调好,但一旦你自定义中间件并加到 $middleware 开头或中间,就可能破坏这个链条。例如:

  • 把自定义日志中间件放在 EncryptCookies 之前 → 读不到解密后的 cookie
  • 把权限中间件放在 StartSession 之前 → $request->user() 为 null
  • api 组里错误加入 StartSession → API 请求无状态,session 写入无效且可能引发异常

中间件参数传递靠字符串语法,不能传对象或复杂结构

路由绑定中间件时支持传参,但仅限简单值,语法是 middleware('role:admin,editor'),对应 handle($request, $next, ...$roles) 中的 $roles = ['admin', 'editor']

注意限制:

  • 参数只能是字符串,用英文逗号分隔,不能带空格('role:admin, editor' 会导致 $roles[1]" editor"
  • 无法传数组字面量、布尔值或变量引用,比如 middleware('throttle:60,1,true') 中最后一个 true 仍是字符串
  • 若需动态逻辑(如根据 URL 参数决定角色),应在中间件内部解析 $request,而不是试图塞进参数

参数本质是 Laravel 在解析路由时做的字符串切割,没有类型推断,也不经过 DI 容器。

中间件真正的复杂点不在写法,而在它横跨请求生命周期的两个方向:进入时可修改 $request,退出时可修改 $response。很多人只关注“拦不拦”,却忘了返回的 $response 会被上游中间件再次处理——比如你在底层加了 X-Processed-By: MyMiddleware,但上层某个中间件又调用了 $response->withHeaders([]),这个 header 就丢了。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2449

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1571

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1473

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

951

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1414

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1305

2023.11.13

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 6.9万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号