Merge branch '2.8' into 3.3
* 2.8: [appveyor] set memory_limit=-1 [Router] Skip anonymous classes when loading annotated routes Fixed Request::__toString ignoring cookies [Security] Fix fatal error on non string username
This commit is contained in:
commit
2f8e1b86ea
|
@ -27,6 +27,7 @@ install:
|
|||
- 7z x php_memcache-3.0.8-5.5-nts-vc11-x86.zip -y >nul
|
||||
- cd ..
|
||||
- copy /Y php.ini-development php.ini-min
|
||||
- echo memory_limit=-1 >> php.ini-min
|
||||
- echo serialize_precision=14 >> php.ini-min
|
||||
- echo max_execution_time=1200 >> php.ini-min
|
||||
- echo date.timezone="America/Los_Angeles" >> php.ini-min
|
||||
|
|
|
@ -531,9 +531,21 @@ class Request
|
|||
return trigger_error($e, E_USER_ERROR);
|
||||
}
|
||||
|
||||
$cookieHeader = '';
|
||||
$cookies = array();
|
||||
|
||||
foreach ($this->cookies as $k => $v) {
|
||||
$cookies[] = $k.'='.$v;
|
||||
}
|
||||
|
||||
if (!empty($cookies)) {
|
||||
$cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
|
||||
}
|
||||
|
||||
return
|
||||
sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
|
||||
$this->headers."\r\n".
|
||||
$this->headers.
|
||||
$cookieHeader."\r\n".
|
||||
$content;
|
||||
}
|
||||
|
||||
|
|
|
@ -1523,8 +1523,18 @@ class RequestTest extends TestCase
|
|||
$request = new Request();
|
||||
|
||||
$request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
|
||||
$request->cookies->set('Foo', 'Bar');
|
||||
|
||||
$this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString());
|
||||
$asString = (string) $request;
|
||||
|
||||
$this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
|
||||
$this->assertContains('Cookie: Foo=Bar', $asString);
|
||||
|
||||
$request->cookies->set('Another', 'Cookie');
|
||||
|
||||
$asString = (string) $request;
|
||||
|
||||
$this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
|
||||
}
|
||||
|
||||
public function testIsMethod()
|
||||
|
|
|
@ -112,22 +112,22 @@ class AnnotationFileLoader extends FileLoader
|
|||
}
|
||||
|
||||
if (T_CLASS === $token[0]) {
|
||||
// Skip usage of ::class constant
|
||||
$isClassConstant = false;
|
||||
// Skip usage of ::class constant and anonymous classes
|
||||
$skipClassToken = false;
|
||||
for ($j = $i - 1; $j > 0; --$j) {
|
||||
if (!isset($tokens[$j][1])) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (T_DOUBLE_COLON === $tokens[$j][0]) {
|
||||
$isClassConstant = true;
|
||||
if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
|
||||
$skipClassToken = true;
|
||||
break;
|
||||
} elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isClassConstant) {
|
||||
if (!$skipClassToken) {
|
||||
$class = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Routing\Tests\Fixtures\OtherAnnotatedClasses;
|
||||
|
||||
trait AnonymousClassInTrait
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
return new class() {
|
||||
public function foo()
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -67,6 +67,17 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
|
|||
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/VariadicClass.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 7.0
|
||||
*/
|
||||
public function testLoadAnonymousClass()
|
||||
{
|
||||
$this->reader->expects($this->never())->method('getClassAnnotation');
|
||||
$this->reader->expects($this->never())->method('getMethodAnnotations');
|
||||
|
||||
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php');
|
||||
}
|
||||
|
||||
public function testSupports()
|
||||
{
|
||||
$fixture = __DIR__.'/../Fixtures/annotated.php';
|
||||
|
|
|
@ -43,8 +43,6 @@ class ContextListener implements ListenerInterface
|
|||
private $registered;
|
||||
private $trustResolver;
|
||||
|
||||
private static $unserializeExceptionCode = 0x37313bc;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
|
||||
{
|
||||
if (empty($contextKey)) {
|
||||
|
@ -185,7 +183,7 @@ class ContextListener implements ListenerInterface
|
|||
$prevUnserializeHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
|
||||
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler) {
|
||||
if (__FILE__ === $file) {
|
||||
throw new \UnexpectedValueException($msg, self::$unserializeExceptionCode);
|
||||
throw new \UnexpectedValueException($msg, 0x37313bc);
|
||||
}
|
||||
|
||||
return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false;
|
||||
|
@ -199,7 +197,7 @@ class ContextListener implements ListenerInterface
|
|||
restore_error_handler();
|
||||
ini_set('unserialize_callback_func', $prevUnserializeHandler);
|
||||
if ($e) {
|
||||
if (!$e instanceof \UnexpectedValueException || self::$unserializeExceptionCode !== $e->getCode()) {
|
||||
if (!$e instanceof \UnexpectedValueException || 0x37313bc !== $e->getCode()) {
|
||||
throw $e;
|
||||
}
|
||||
if ($this->logger) {
|
||||
|
@ -215,6 +213,6 @@ class ContextListener implements ListenerInterface
|
|||
*/
|
||||
public static function handleUnserializeCallback($class)
|
||||
{
|
||||
throw new \UnexpectedValueException('Class not found: '.$class, self::$unserializeExceptionCode);
|
||||
throw new \UnexpectedValueException('Class not found: '.$class, 0x37313bc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
|
|||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
|
@ -98,15 +99,17 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener
|
|||
}
|
||||
}
|
||||
|
||||
if ($this->options['post_only']) {
|
||||
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
|
||||
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
|
||||
} else {
|
||||
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
|
||||
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
|
||||
$requestBag = $this->options['post_only'] ? $request->request : $request;
|
||||
$username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']);
|
||||
$password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']);
|
||||
|
||||
if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
|
||||
}
|
||||
|
||||
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
|
||||
$username = trim($username);
|
||||
|
||||
if (\strlen($username) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Http\Firewall;
|
|||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
|
@ -76,14 +77,16 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
|
|||
}
|
||||
}
|
||||
|
||||
if ($this->options['post_only']) {
|
||||
$username = trim(ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']));
|
||||
$password = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']);
|
||||
} else {
|
||||
$username = trim(ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']));
|
||||
$password = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']);
|
||||
$requestBag = $this->options['post_only'] ? $request->request : $request;
|
||||
$username = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['username_parameter']);
|
||||
$password = ParameterBagUtils::getParameterBagValue($requestBag, $this->options['password_parameter']);
|
||||
|
||||
if (!\is_string($username) || (\is_object($username) && !\method_exists($username, '__toString'))) {
|
||||
throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($username)));
|
||||
}
|
||||
|
||||
$username = trim($username);
|
||||
|
||||
if (strlen($username) > Security::MAX_USERNAME_LENGTH) {
|
||||
throw new BadCredentialsException('Invalid username.');
|
||||
}
|
||||
|
|
|
@ -14,8 +14,15 @@ namespace Symfony\Component\Security\Tests\Http\Firewall;
|
|||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
|
||||
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler;
|
||||
use Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener;
|
||||
use Symfony\Component\Security\Http\HttpUtils;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;
|
||||
|
||||
class UsernamePasswordFormAuthenticationListenerTest extends TestCase
|
||||
{
|
||||
|
@ -69,6 +76,31 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase
|
|||
$listener->handle($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
* @expectedExceptionMessage The key "_username" must be a string, "array" given.
|
||||
*/
|
||||
public function testHandleNonStringUsername()
|
||||
{
|
||||
$request = Request::create('/login_check', 'POST', array('_username' => array()));
|
||||
$request->setSession($this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock());
|
||||
|
||||
$listener = new UsernamePasswordFormAuthenticationListener(
|
||||
new TokenStorage(),
|
||||
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(),
|
||||
new SessionAuthenticationStrategy(SessionAuthenticationStrategy::NONE),
|
||||
$httpUtils = new HttpUtils(),
|
||||
'foo',
|
||||
new DefaultAuthenticationSuccessHandler($httpUtils),
|
||||
new DefaultAuthenticationFailureHandler($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $httpUtils),
|
||||
array('require_previous_session' => false)
|
||||
);
|
||||
|
||||
$event = new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST);
|
||||
|
||||
$listener->handle($event);
|
||||
}
|
||||
|
||||
public function getUsernameForLength()
|
||||
{
|
||||
return array(
|
||||
|
|
Reference in New Issue