一、属性
1. $_secureForwardedHeaderParts 安全的forwarded请求头部分
// 信任的`Forwarded`请求头部分
private $_secureForwardedHeaderParts;
二、方法
1. getSecureForwardedHeaderTrustedPart方法,返回Forwarded头对应部分的第一个值
// 返回`Forwarded`请求头对应的第一个值
protected function getSecureForwardedHeaderTrustedPart($token)
{
$token = strtolower($token);
if ($parts = $this->getSecureForwardedHeaderTrustedParts()) {
$lastElement = array_pop($parts);
if ($lastElement && isset($lastElement[$token])) {
return $lastElement[$token];
}
}
return null;
}
2. getSecureForwardedHeaderTrustedParts方法,解析`Forwarded`请求头
// 解析`Forwarded`请求头
protected function getSecureForwardedHeaderTrustedParts()
{
$validator = $this->getIpValidator();
$trustedHosts = [];
foreach ($this->trustedHosts as $trustedCidr => $trustedCidrOrHeaders) {
if (!is_array($trustedCidrOrHeaders)) {
$trustedCidr = $trustedCidrOrHeaders;
}
$trustedHosts[] = $trustedCidr;
}
$validator->setRanges($trustedHosts);
return array_filter($this->getSecureForwardedHeaderParts(), function ($headerPart) use ($validator) {
return isset($headerPart['for']) ?
!$validator->validate($headerPart['for']) :
true;
});
}
3. getSecureForwardedHeaderParts方法,解析Forwarded请求头
// forwarded请求头 类似:
// Forwarded: for=10.0.0.1,for=20.30.40.50;host=php.net,host=awesome.proxy.com;proto=https,proto=http
protected function getSecureForwardedHeaderParts()
{
if ($this->_secureForwardedHeaderParts !== null) {
return $this->_secureForwardedHeaderParts;
}
// 不在安全头数组里,
// 直接返回空数组
if (count(preg_grep('/^forwarded$/i', $this->secureHeaders)) === 0) {
return $this->_secureForwardedHeaderParts = [];
}
/*
* First header is always correct, because proxy CAN add headers
* after last one is found.
* Keep in mind that it is NOT enforced, therefore we cannot be
* sure, that this is really a first one.
*
* FPM keeps last header sent which is a bug. You need to merge
* headers together on your web server before letting FPM handle it
* @see https://bugs.php.net/bug.php?id=78844
*/
$forwarded = $this->headers->get('Forwarded', '');
if ($forwarded === '') {
return $this->_secureForwardedHeaderParts = [];
}
preg_match_all('/(?:[^",]++|"[^"]++")+/', $forwarded, $forwardedElements);
foreach ($forwardedElements[0] as $forwardedPairs) {
preg_match_all(
'/(?P<key>\w+)\s*=\s*(?:(?P<value>[^",;]*[^",;\s])|"(?P<value2>[^"]+)")/',
$forwardedPairs,
$matches,
PREG_SET_ORDER
);
// 解析头
$this->_secureForwardedHeaderParts[] = array_reduce($matches, function ($carry, $item) {
$value = $item['value'];
if (isset($item['value2']) && $item['value2'] !== '') {
$value = $item['value2'];
}
$carry[strtolower($item['key'])] = $value;
return $carry;
}, []);
}
return $this->_secureForwardedHeaderParts;
}
总结:
阅读了1个属性和3个方法:
- $_secureForwardedHeaderParts 安全的forwarded请求头部分
- getSecureForwardedHeaderTrustedPart方法,返回Forwarded头对应部分的第一个值
- getSecureForwardedHeaderTrustedParts方法,解析`Forwarded`请求头
- getSecureForwardedHeaderParts方法,解析Forwarded请求头