Fixes #14488: Added support for X-Forwarded-Host to yii\web\Request, fixed getServerPort() usage

This commit is contained in:
Alexander Makarov
2018-02-07 00:01:50 +03:00
committed by GitHub
parent 40b038379f
commit 7bafb7bf09
3 changed files with 94 additions and 7 deletions

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.14 under development 2.0.14 under development
------------------------ ------------------------
- Enh #14488: Added support for X-Forwarded-Host to `yii\web\Request`, fixed `getServerPort()` usage (si294r, samdark)
- Enh #13019: Support JSON in SchemaBuilderTrait (zhukovra, undefinedor) - Enh #13019: Support JSON in SchemaBuilderTrait (zhukovra, undefinedor)
- Enh #15047: `yii\db\Query::select()` and `yii\db\Query::addSelect()` now check for duplicate column names (wapmorgan) - Enh #15047: `yii\db\Query::select()` and `yii\db\Query::addSelect()` now check for duplicate column names (wapmorgan)
- Enh #14643: Added `yii\web\ErrorAction::$layout` property to conveniently set layout from error action config (swods, cebe, samdark) - Enh #14643: Added `yii\web\ErrorAction::$layout` property to conveniently set layout from error action config (swods, cebe, samdark)

View File

@ -218,9 +218,12 @@ class Request extends \yii\base\Request
* @since 2.0.13 * @since 2.0.13
*/ */
public $secureHeaders = [ public $secureHeaders = [
// Common:
'X-Forwarded-For', 'X-Forwarded-For',
'X-Forwarded-Host', 'X-Forwarded-Host',
'X-Forwarded-Proto', 'X-Forwarded-Proto',
// Microsoft:
'Front-End-Https', 'Front-End-Https',
'X-Rewrite-Url', 'X-Rewrite-Url',
]; ];
@ -233,7 +236,7 @@ class Request extends \yii\base\Request
* @since 2.0.13 * @since 2.0.13
*/ */
public $ipHeaders = [ public $ipHeaders = [
'X-Forwarded-For', 'X-Forwarded-For', // Common
]; ];
/** /**
* @var array list of headers to check for determining whether the connection is made via HTTPS. * @var array list of headers to check for determining whether the connection is made via HTTPS.
@ -245,8 +248,8 @@ class Request extends \yii\base\Request
* @since 2.0.13 * @since 2.0.13
*/ */
public $secureProtocolHeaders = [ public $secureProtocolHeaders = [
'X-Forwarded-Proto' => ['https'], 'X-Forwarded-Proto' => ['https'], // Common
'Front-End-Https' => ['on'], 'Front-End-Https' => ['on'], // Microsoft
]; ];
/** /**
@ -705,7 +708,10 @@ class Request extends \yii\base\Request
if ($this->_hostInfo === null) { if ($this->_hostInfo === null) {
$secure = $this->getIsSecureConnection(); $secure = $this->getIsSecureConnection();
$http = $secure ? 'https' : 'http'; $http = $secure ? 'https' : 'http';
if ($this->headers->has('Host')) {
if ($this->headers->has('X-Forwarded-Host')) {
$this->_hostInfo = $http . '://' . $this->headers->get('X-Forwarded-Host');
} elseif ($this->headers->has('Host')) {
$this->_hostInfo = $http . '://' . $this->headers->get('Host'); $this->_hostInfo = $http . '://' . $this->headers->get('Host');
} elseif (isset($_SERVER['SERVER_NAME'])) { } elseif (isset($_SERVER['SERVER_NAME'])) {
$this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME']; $this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME'];
@ -1217,7 +1223,8 @@ class Request extends \yii\base\Request
public function getPort() public function getPort()
{ {
if ($this->_port === null) { if ($this->_port === null) {
$this->_port = !$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : 80; $serverPort = $this->getServerPort();
$this->_port = !$this->getIsSecureConnection() && $serverPort !== null ? $serverPort : 80;
} }
return $this->_port; return $this->_port;
@ -1249,7 +1256,8 @@ class Request extends \yii\base\Request
public function getSecurePort() public function getSecurePort()
{ {
if ($this->_securePort === null) { if ($this->_securePort === null) {
$this->_securePort = $this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : 443; $serverPort = $this->getServerPort();
$this->_securePort = $this->getIsSecureConnection() && $serverPort !== null ? $serverPort : 443;
} }
return $this->_securePort; return $this->_securePort;

View File

@ -266,7 +266,85 @@ class RequestTest extends TestCase
$this->assertEquals($_GET, ['id' => 63]); $this->assertEquals($_GET, ['id' => 63]);
} }
public function testGetHostInfo() public function getHostInfoDataProvider()
{
return [
// empty
[
[],
[null, null]
],
// normal
[
[
'HTTP_HOST' => 'example1.com',
'SERVER_NAME' => 'example2.com',
],
[
'http://example1.com',
'example1.com',
]
],
// HTTP header missing
[
[
'SERVER_NAME' => 'example2.com',
],
[
'http://example2.com',
'example2.com',
]
],
// forwarded from untrusted server
[
[
'HTTP_X_FORWARDED_HOST' => 'example3.com',
'HTTP_HOST' => 'example1.com',
'SERVER_NAME' => 'example2.com',
],
[
'http://example1.com',
'example1.com',
]
],
// forwarded from trusted proxy
[
[
'HTTP_X_FORWARDED_HOST' => 'example3.com',
'HTTP_HOST' => 'example1.com',
'SERVER_NAME' => 'example2.com',
'REMOTE_ADDR' => '192.168.0.1',
],
[
'http://example3.com',
'example3.com',
]
],
];
}
/**
* @dataProvider getHostInfoDataProvider
* @param array $server
* @param array $expected
*/
public function testGetHostInfo($server, $expected)
{
$original = $_SERVER;
$_SERVER = $server;
$request = new Request([
'trustedHosts' => [
'192.168.0.0/24',
],
]);
$this->assertEquals($expected[0], $request->getHostInfo());
$this->assertEquals($expected[1], $request->getHostName());
$_SERVER = $original;
}
public function testSetHostInfo()
{ {
$request = new Request(); $request = new Request();