Merge branch '3.4' into 4.0

* 3.4:
  [Routing] Fix throwing NoConfigurationException instead of 405
  [Security] Load the user before pre/post auth checks when needed
  [SecurityBundle] Add test for simple authentication config
  [WebProfilerBundle] fix version check
  [SecurityBundle] Add missing argument to security.authentication.provider.simple
  [Finder] fix tests
This commit is contained in:
Nicolas Grekas 2018-04-04 15:50:32 +02:00
commit bc23cae7b0
20 changed files with 140 additions and 12 deletions

View File

@ -49,6 +49,7 @@ class SimplePreAuthenticationFactory implements SecurityFactoryInterface
->replaceArgument(0, new Reference($config['authenticator']))
->replaceArgument(1, new Reference($userProvider))
->replaceArgument(2, $id)
->replaceArgument(3, new Reference('security.user_checker.'.$id))
;
// listener

View File

@ -199,6 +199,7 @@
<argument /> <!-- Simple Authenticator -->
<argument /> <!-- User Provider -->
<argument /> <!-- Provider-shared Key -->
<argument>null</argument> <!-- UserChecker -->
</service>
<service id="security.authentication.provider.pre_authenticated" class="Symfony\Component\Security\Core\Authentication\Provider\PreAuthenticatedAuthenticationProvider" abstract="true">

View File

@ -148,6 +148,23 @@ abstract class CompleteConfigurationTest extends TestCase
),
null,
),
array(
'simple_auth',
'security.user_checker',
null,
true,
false,
'security.user.provider.concrete.default',
'simple_auth',
'security.authentication.form_entry_point.simple_auth',
null,
null,
array(
'simple_form',
'anonymous',
),
null,
),
), $configs);
$this->assertEquals(array(
@ -178,6 +195,13 @@ abstract class CompleteConfigurationTest extends TestCase
'security.authentication.listener.anonymous.with_user_checker',
'security.access_listener',
),
array(
'security.channel_listener',
'security.context_listener.2',
'security.authentication.listener.simple_form.simple_auth',
'security.authentication.listener.anonymous.simple_auth',
'security.access_listener',
),
), $listeners);
$this->assertFalse($container->hasAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', 'No user checker alias is registered when custom user checker services are registered'));

View File

@ -90,6 +90,12 @@ $container->loadFromExtension('security', array(
'http_basic' => true,
'logout_on_user_change' => true,
),
'simple_auth' => array(
'provider' => 'default',
'anonymous' => true,
'simple_form' => array('authenticator' => 'simple_authenticator'),
'logout_on_user_change' => true,
),
),
'access_control' => array(

View File

@ -68,6 +68,11 @@
<user-checker>app.user_checker</user-checker>
</firewall>
<firewall name="simple_auth" logout-on-user-change="true" provider="default">
<anonymous />
<simple-form authenticator="simple_authenticator" />
</firewall>
<role id="ROLE_ADMIN">ROLE_USER</role>
<role id="ROLE_SUPER_ADMIN">ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH</role>
<role id="ROLE_REMOTE">ROLE_USER,ROLE_ADMIN</role>

View File

@ -73,6 +73,12 @@ security:
user_checker: app.user_checker
logout_on_user_change: true
simple_auth:
provider: default
anonymous: ~
simple_form: { authenticator: simple_authenticator }
logout_on_user_change: true
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

View File

@ -55,7 +55,7 @@ class WebProfilerExtension extends Extension
$container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED);
}
if (Kernel::VERSION_ID >= 30408 || Kernel::VERSION_ID >= 40008) {
if (Kernel::VERSION_ID >= 40008 || (Kernel::VERSION_ID >= 30408 && Kernel::VERSION_ID < 40000)) {
$container->getDefinition('debug.file_link_formatter')
->replaceArgument(3, new ServiceClosureArgument(new Reference('debug.file_link_formatter.url_format')));
}

View File

@ -154,7 +154,7 @@ EOF;
}
// used to display the Welcome Page in apps that don't define a homepage
$code .= " if ('/' === \$pathinfo) {\n";
$code .= " if ('/' === \$pathinfo && !\$allow) {\n";
$code .= " throw new Symfony\Component\Routing\Exception\NoConfigurationException();\n";
$code .= " }\n";
@ -362,7 +362,7 @@ EOF;
EOF;
}
} elseif ($methods) {
$code .= <<<EOF
$code .= <<<EOF
if (!in_array($methodVariable, array('$methods'))) {
\$allow = array_merge(\$allow, array('$methods'));
goto $gotoname;

View File

@ -76,7 +76,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
return $ret;
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$this->allow) {
throw new NoConfigurationException();
}

View File

@ -28,7 +28,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
$canonicalMethod = 'GET';
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -309,7 +309,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -371,7 +371,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
not_nonsecure:
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -46,7 +46,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
return array('_route' => 'with-condition');
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -103,7 +103,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -200,7 +200,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -204,7 +204,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -240,7 +240,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
}
if ('/' === $pathinfo) {
if ('/' === $pathinfo && !$allow) {
throw new Symfony\Component\Routing\Exception\NoConfigurationException();
}

View File

@ -45,6 +45,21 @@ class UrlMatcherTest extends TestCase
}
}
public function testMethodNotAllowedOnRoot()
{
$coll = new RouteCollection();
$coll->add('foo', new Route('/', array(), array(), array(), '', array(), array('GET')));
$matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST'));
try {
$matcher->match('/');
$this->fail();
} catch (MethodNotAllowedException $e) {
$this->assertEquals(array('GET'), $e->getAllowedMethods());
}
}
public function testHeadAllowedWhenRequirementContainsGet()
{
$coll = new RouteCollection();

View File

@ -11,8 +11,11 @@
namespace Symfony\Component\Security\Core\Authentication\Provider;
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserChecker;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
@ -45,6 +48,24 @@ class SimpleAuthenticationProvider implements AuthenticationProviderInterface
}
$user = $authToken->getUser();
if (!$user instanceof UserInterface) {
try {
$user = $this->userProvider->loadUserByUsername($user);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
} catch (UsernameNotFoundException $e) {
$e->setUsername($user);
throw $e;
} catch (\Exception $e) {
$e = new AuthenticationServiceException($e->getMessage(), 0, $e);
$e->setToken($token);
throw $e;
}
}
$this->userChecker->checkPreAuth($user);
$this->userChecker->checkPostAuth($user);

View File

@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Exception\DisabledException;
use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider;
use Symfony\Component\Security\Core\Exception\LockedException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
class SimpleAuthenticationProviderTest extends TestCase
{
@ -72,6 +73,54 @@ class SimpleAuthenticationProviderTest extends TestCase
$provider->authenticate($token);
}
public function testAuthenticateFromString()
{
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$token->expects($this->any())
->method('getUser')
->will($this->returnValue('foo'));
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock();
$authenticator->expects($this->once())
->method('authenticateToken')
->will($this->returnValue($token));
$userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock();
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willReturn($this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock());
$provider = $this->getProvider($authenticator, $userProvider);
$this->assertSame($token, $provider->authenticate($token));
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\UsernameNotFoundException
*/
public function testUsernameNotFound()
{
$user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$token->expects($this->any())
->method('getUser')
->will($this->returnValue('foo'));
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock();
$authenticator->expects($this->once())
->method('authenticateToken')
->will($this->returnValue($token));
$userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock();
$userProvider->expects($this->once())
->method('loadUserByUsername')
->willThrowException(new UsernameNotFoundException());
$this->getProvider($authenticator, $userProvider)->authenticate($token);
}
protected function getProvider($simpleAuthenticator = null, $userProvider = null, $userChecker = null, $key = 'test')
{
if (null === $userChecker) {