laravel自定义中间件必须用php artisan make:middleware生成、handle()中必须调用$next($request)、注册方式决定是否执行;手动建文件、漏调$next或注册错误均导致中间件静默失效。

直接说结论:Laravel 自定义中间件不是“写个类就行”,关键在三处——必须用 php artisan make:middleware 生成、handle() 里必须调用 $next($request)、注册方式决定它到底会不会执行。漏掉任一环,中间件就等于没写。
中间件类为什么死活不执行?
最常见原因是手动新建文件,哪怕路径、命名空间、方法签名全对,Laravel 也不会加载它。Artisan 命令不只是建文件,还触发自动加载注册和 PSR-4 兼容校验。
- 必须用
php artisan make:middleware IpWhitelist,不能手建app/Http/Middleware/IpWhitelist.php - 类必须放在
app/Http/Middleware/目录下,命名空间严格为namespace App\Http\Middleware; - 注册时若用别名(如
'ip.whitelist' => \App\Http\Middleware\IpWhitelist::class),路由中必须写->middleware('ip.whitelist'),写成->middleware(IpWhitelist::class)会失败
handle() 里怎么取真实 IP 才可靠?
别直接读 $_SERVER['REMOTE_ADDR'],也别无脑信 $request->ip() —— 它在 Nginx + 负载均衡或 Cloudflare 后面大概率返回 127.0.0.1 或代理 IP。
- 先确认
App\Http\Middleware\TrustProxies中的$proxies已设为实际代理网段,例如['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] - 检查
$headers属性是否包含Illuminate\Http\Request::HEADER_X_FORWARDED_FOR(默认已启用) - Cloudflare 用户需额外加入其官方 IP 段,并确保环境变量
APP_TRUSTED_PROXIES不是*(仅限内网调试)
白名单匹配逻辑怎么写才不踩坑?
基础版用精确匹配即可,别一上来就手写 CIDR 解析——PHP 原生不支持,自己位运算极易出错且难维护。
- 白名单建议从配置读取,比如
config/whitelist.php返回数组:return ['192.168.1.100', '2001:db8::1'] - 比对用
in_array($request->ip(), $whitelist, true),注意第三个参数true防止类型转换误判 - 不匹配时用
return response('', 403),别用abort(403)—— 它会走完整异常渲染流程,多一次视图编译开销 - CLI 环境下
$request->ip()可能为 null,加一层判断:if (php_sapi_name() === 'cli') { return $next($request); }
真正麻烦的从来不是写逻辑,而是部署后发现 IP 总是不对、中间件突然不触发、或者本地 OK 上了服务器就 403 —— 这些基本都卡在 TrustProxies 配置、注册别名拼写、以及 CLI 和 HTTP 环境差异上。











