Laravel 11 中禁止 IP 直接访问必须在 Nginx/Apache 层实现,因其在请求入口拦截 Host 头、节省 PHP 资源且覆盖所有请求;中间件仅作补充校验,无法处理静态资源或未路由请求。

在 Laravel 11 中,**不能靠中间件完全实现“禁止 IP 直接访问、只允许域名访问”**——因为该限制本质属于 HTTP 协议层的主机头(Host)校验,应在 Web 服务器(如 Nginx/Apache)或反向代理层完成。Laravel 中间件运行在请求已进入 PHP 应用之后,此时 Host 头已被解析,但若攻击者绕过 Web 服务器直连 PHP-FPM(极少见)或伪造 Host 头,中间件才可作为补充校验手段。
为什么优先用 Nginx/Apache 而非中间件?
– Web 服务器在接收请求第一刻就可拦截非法 Host,不消耗 PHP 资源
– 返回 444(Nginx 特有,静默关闭连接)或 403,响应更快、更干净
– Laravel 中间件无法阻止未触发路由的静态资源请求(如 public/xxx.js),而 Web 服务器可统一拦截所有请求
Web 服务器层推荐配置(必须做)
Nginx 示例(推荐使用 444):
server {
listen 80;
server_name example.com; # 替换为你的真实域名
if ($host != 'example.com') {
return 444; # 静默丢弃,不返回任何响应
}
# 其余配置...
}Apache 示例(.htaccess 或虚拟主机):
RewriteEngine On
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^ - [F]✅ 效果:用户用 http://192.168.1.100 或 http://服务器IP 访问时,直接被 Web 服务器拒绝,Laravel 完全不参与处理。
若需 Laravel 层补充校验(仅限路由请求)
适用于:你确信所有流量都经由 Web 服务器转发,但仍想在应用层多加一道保险(例如防止 Host 头被篡改、或配合日志审计)。
创建中间件:
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
php artisan make:middleware RequireDomain
编辑 app/Http/Middleware/RequireDomain.php:
public function handle(Request $request, Closure $next)
{
$allowedHosts = ['example.com', 'www.example.com']; // 支持多个域名
$host = $request->getHost();
<pre class='brush:php;toolbar:false;'>if (!in_array($host, $allowedHosts)) {
\Log::warning('Invalid host access blocked', [
'host' => $host,
'ip' => $request->ip(),
'url' => $request->fullUrl()
]);
abort(403, 'Direct IP access is not allowed.');
}
return $next($request);}
注册中间件别名(app/Http/Kernel.php):
'require.domain' => \App\Http\Middleware\RequireDomain::class,
绑定到需要保护的路由组(如全部 Web 路由):
Route::middleware('require.domain')->group(function () {
Route::get('/', function () { return view('welcome'); });
Route::get('/about', fn() => view('about'));
});⚠️ 注意:此中间件对 public/ 下的静态文件、健康检查端点(如 /up)、或未经过路由的请求无效。
关键补充:确保真实 IP 和 Host 可靠获取
若使用 Cloudflare、Nginx 反向代理等,$request->getHost() 和 $request->ip() 可能不准:
- 在
App\Http\Middleware\TrustProxies中设置可信代理 IP(如['127.0.0.1', '10.0.0.0/8']) - 确认
APP_TRUSTED_PROXIES环境变量已正确配置 - 避免依赖
$_SERVER['HTTP_HOST']或$_SERVER['REMOTE_ADDR'],一律用$request->getHost()和$request->ip()

















