全局中间件之 TrustProxies
简介
上一章,我们了解了 第四个 全局中间件 ConvertEmptyStringsToNull
的作用:将空字符串的字段转换为 null
这一章我们了解 最后一个 全局中间件 TrustProxies
。
从字面意思我们知道是 关于设置信任代理有关的中间件
Laravel 官方文档
关于设置信任代理的有关内容--->传送门
通过官方文档,我们知道:
- 设置信任代理的 IP 地址,以及信任代理发过来的头信息都是在
App\Http\Middleware\TrustProxies
这个最后中间件中实现的。 - 不知道代理 IP 的情况下,可以用 * 来解决问题
关于什么情况下设置信任代理
当你的站点(Laravel 所在服务器)位于代理服务器(例如:负载均衡)后面的时候,则每个 Web 请求都有可能始终来自该代理,而不是客户端实际在您的站点上发出请求。
此时,你应该根据代理服务设置的转发头以及代理服务器的 IP 地址来配置你的 Laravel 代理信任。
关于为什么要设置信任代理
如果您的站点位于代理(例如负载均衡器)后面,则您的 Web 应用程序可能存在以下一些问题:
- 重定向和 PHP 生成的 URL 在其 Web 地址,协议和/或端口方面可能不准确。
- 可能无法为每个用户创建唯一会话,从而导致可能访问不正确的帐户,或者无法让用户完全登录
- 记录或其他数据收集过程数据可能看起来来自一个位置(代理本身),使您无法区分各个客户端所采取的流量/操作。
关于上面两个为什么的来源
官方扩展包 fideloper/proxy
关于代理的说法--->传送门
正式进入话题
我们来看一下 TrustProxies
是如何进行代理设置的
其 handle 方法在 TrustProxies
父类 Fideloper\Proxy\TrustProxies
中
Fideloper\Proxy\TrustProxies
<?php
namespace Fideloper\Proxy;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Contracts\Config\Repository;
class TrustProxies
{
//...
/**
* 中间件过滤请求的核心方法
*/
public function handle(Request $request, Closure $next)
{
$request::setTrustedProxies([], $this->getTrustedHeaderNames()); // Reset trusted proxies between requests
$this->setTrustedProxyIpAddresses($request);
return $next($request);
}
/**
* 设置信任代理(例如:负载均衡)的 IP 地址
*/
protected function setTrustedProxyIpAddresses(Request $request)
{
$trustedIps = $this->proxies ?: $this->config->get('trustedproxy.proxies');
// Only trust specific IP addresses
if (is_array($trustedIps)) {
return $this->setTrustedProxyIpAddressesToSpecificIps($request, $trustedIps);
}
// Trust any IP address that calls us
// `**` for backwards compatibility, but is depreciated
if ($trustedIps === '*' || $trustedIps === '**') {
return $this->setTrustedProxyIpAddressesToTheCallingIp($request);
}
}
/**
* 当知道代理服务器 IP 地址时,进行 IP 指定设置
*/
private function setTrustedProxyIpAddressesToSpecificIps(Request $request, $trustedIps)
{
$request->setTrustedProxies((array) $trustedIps, $this->getTrustedHeaderNames());
}
/**
* 当不知道代理服务器 IP 地址时,进行 * 全局设置
*/
private function setTrustedProxyIpAddressesToTheCallingIp(Request $request)
{
$request->setTrustedProxies([$request->server->get('REMOTE_ADDR')], $this->getTrustedHeaderNames());
}
/**
* 获取信任的头信息
*/
protected function getTrustedHeaderNames()
{
return $this->headers ?: $this->config->get('trustedproxy.headers');
}
//...
}
大家可能看到 $request->setTrustedProxies()
方法被调用过好几次,这个方法就是设置信任代理的核心方法,但是非常简单,我们来看一下
Symfony\Component\HttpFoundation\Request
public static function setTrustedProxies(array $proxies, int $trustedHeaderSet)
{
self::$trustedProxies = $proxies;
self::$trustedHeaderSet = $trustedHeaderSet;
}
是不是很简单,就是设置两个静态属性。当后面需要设置重定向,保存日志,设置 session 时,应该会用到这个两个静态属性,具体需要我们一起学到才能知道。
最后,关于官方扩展包的另外一种设置信任 IP 和信任头的方法
在
config/app.php
配置文件中添加服务提供者'providers' => array(
/*
* 可信代理服务提供者
*/
Fideloper\Proxy\TrustedProxyServiceProvider::class,
);生成 config 配置文件
$ php artisan vendor:publish --provider="Fideloper\Proxy\TrustedProxyServiceProvider"
替换掉
App\Http\Middleware\TrustProxies
全局中间件App\Http\Kernel
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class . ':foo,bar',
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Fideloper\Proxy\TrustProxies::class, // 原先的是 \App\Http\Middleware\TrustProxies::class,
];
// ...
}现在我们就可以在 config 配置文件中进行 代理信任 配置了
写在最后
由于没有用过 Laravel 关于信任代理方面的功能。上面解说,我仅从源代码和相关文档,整理得来,具体使用效果,有经验的童鞋,可以评论区发表出来,大家一起学习。