Browse Source

Fix #18648: Fix `yii\web\Request` to properly handle HTTP Basic Auth headers

tags/2.0.43
olegbaturin 3 years ago committed by GitHub
parent
commit
e83a86fd30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/CHANGELOG.md
  2. 21
      framework/web/Request.php
  3. 13
      tests/framework/filters/auth/BasicAuthTest.php
  4. 13
      tests/framework/web/RequestTest.php

1
framework/CHANGELOG.md

@ -12,6 +12,7 @@ Yii Framework 2 Change Log
- Enh #18676: Added method `yii\helpers\BaseFileHelper::changeOwnership()` and properties `newFileMode`/`newFileOwnership` in `yii\console\controllers\BaseMigrateController` (rhertogh)
- Bug #18678: Fix `yii\caching\DbCache` to use configured cache table name instead of the default one in case of MSSQL varbinary column type detection (aidanbek)
- Enh #18695: Added `yii\web\Cookie::SAME_SITE_NONE` constant (rhertogh)
- Bug #18648: Fix `yii\web\Request` to properly handle HTTP Basic Auth headers (olegbaturin)
- Enh #18726: Added `yii\helpers\Json::$prettyPrint` (rhertogh)

21
framework/web/Request.php

@ -371,10 +371,16 @@ class Request extends \yii\base\Request
$this->_headers->add($name, $value);
}
} else {
// ['prefix' => length]
$headerPrefixes = ['HTTP_' => 5, 'REDIRECT_HTTP_' => 14];
foreach ($_SERVER as $name => $value) {
if (strncmp($name, 'HTTP_', 5) === 0) {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$this->_headers->add($name, $value);
foreach ($headerPrefixes as $prefix => $length) {
if (strncmp($name, $prefix, $length) === 0) {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, $length)))));
$this->_headers->add($name, $value);
continue 2;
}
}
}
}
@ -1321,13 +1327,16 @@ class Request extends \yii\base\Request
return [$username, $password];
}
/*
/**
* Apache with php-cgi does not pass HTTP Basic authentication to PHP by default.
* To make it work, add the following line to to your .htaccess file:
* To make it work, add one of the following lines to to your .htaccess file:
*
* SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0
* --OR--
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
*/
$auth_token = $this->getHeaders()->get('HTTP_AUTHORIZATION') ?: $this->getHeaders()->get('REDIRECT_HTTP_AUTHORIZATION');
$auth_token = $this->getHeaders()->get('Authorization');
if ($auth_token !== null && strncasecmp($auth_token, 'basic', 5) === 0) {
$parts = array_map(function ($value) {
return strlen($value) === 0 ? null : $value;

13
tests/framework/filters/auth/BasicAuthTest.php

@ -27,10 +27,13 @@ class BasicAuthTest extends AuthTest
*/
public function testHttpBasicAuth($token, $login)
{
$original = $_SERVER;
$_SERVER['PHP_AUTH_USER'] = $token;
$_SERVER['PHP_AUTH_PW'] = 'whatever, we are testers';
$filter = ['class' => HttpBasicAuth::className()];
$this->ensureFilterApplies($token, $login, $filter);
$_SERVER = $original;
}
/**
@ -40,9 +43,12 @@ class BasicAuthTest extends AuthTest
*/
public function testHttpBasicAuthWithHttpAuthorizationHeader($token, $login)
{
Yii::$app->request->headers->set('HTTP_AUTHORIZATION', 'Basic ' . base64_encode($token . ':' . 'mypw'));
$original = $_SERVER;
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic ' . base64_encode($token . ':' . 'mypw');
$filter = ['class' => HttpBasicAuth::className()];
$this->ensureFilterApplies($token, $login, $filter);
$_SERVER = $original;
}
/**
@ -52,9 +58,12 @@ class BasicAuthTest extends AuthTest
*/
public function testHttpBasicAuthWithRedirectHttpAuthorizationHeader($token, $login)
{
Yii::$app->request->headers->set('REDIRECT_HTTP_AUTHORIZATION', 'Basic ' . base64_encode($token . ':' . 'mypw'));
$original = $_SERVER;
$_SERVER['REDIRECT_HTTP_AUTHORIZATION'] = 'Basic ' . base64_encode($token . ':' . 'mypw');
$filter = ['class' => HttpBasicAuth::className()];
$this->ensureFilterApplies($token, $login, $filter);
$_SERVER = $original;
}
/**

13
tests/framework/web/RequestTest.php

@ -991,18 +991,21 @@ class RequestTest extends TestCase
*/
public function testHttpAuthCredentialsFromHttpAuthorizationHeader($secret, $expected)
{
$request = new Request();
$original = $_SERVER;
$request->getHeaders()->set('HTTP_AUTHORIZATION', 'Basic ' . $secret);
$request = new Request();
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic ' . $secret;
$this->assertSame($request->getAuthCredentials(), $expected);
$this->assertSame($request->getAuthUser(), $expected[0]);
$this->assertSame($request->getAuthPassword(), $expected[1]);
$request->getHeaders()->offsetUnset('HTTP_AUTHORIZATION');
$_SERVER = $original;
$request->getHeaders()->set('REDIRECT_HTTP_AUTHORIZATION', 'Basic ' . $secret);
$request = new Request();
$_SERVER['REDIRECT_HTTP_AUTHORIZATION'] = 'Basic ' . $secret;
$this->assertSame($request->getAuthCredentials(), $expected);
$this->assertSame($request->getAuthUser(), $expected[0]);
$this->assertSame($request->getAuthPassword(), $expected[1]);
$_SERVER = $original;
}
public function testHttpAuthCredentialsFromServerSuperglobal()
@ -1013,7 +1016,7 @@ class RequestTest extends TestCase
$_SERVER['PHP_AUTH_PW'] = $pw;
$request = new Request();
$request->getHeaders()->set('HTTP_AUTHORIZATION', 'Basic ' . base64_encode('less-priority:than-PHP_AUTH_*'));
$request->getHeaders()->set('Authorization', 'Basic ' . base64_encode('less-priority:than-PHP_AUTH_*'));
$this->assertSame($request->getAuthCredentials(), [$user, $pw]);
$this->assertSame($request->getAuthUser(), $user);

Loading…
Cancel
Save