Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 526f756

Browse filesBrowse files
committed
Added GuardManagerListener
This replaces all individual authentication listeners when guard authentication manager is enabled.
1 parent a172bac commit 526f756
Copy full SHA for 526f756

File tree

6 files changed

+314
-122
lines changed
Filter options

6 files changed

+314
-122
lines changed

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,24 @@ private function createFirewalls(array $config, ContainerBuilder $container)
264264
// add authentication providers to authentication manager
265265
$authenticationProviders = array_map(function ($id) {
266266
return new Reference($id);
267-
}, array_values(array_unique($authenticationProviders)));
267+
}, array_unique($authenticationProviders));
268268
$authenticationManagerId = 'security.authentication.manager.provider';
269269
if ($this->guardAuthenticationManagerEnabled) {
270270
$authenticationManagerId = 'security.authentication.manager.guard';
271271
$container->setAlias('security.authentication.manager', new Alias($authenticationManagerId));
272+
273+
// guard authentication manager listener
274+
$container
275+
->setDefinition('security.firewall.guard.'.$name.'locator', new ChildDefinition('security.firewall.guard.locator'))
276+
->setArguments([$authenticationProviders])
277+
->addTag('container.service_locator')
278+
;
279+
$container
280+
->setDefinition('security.firewall.guard.'.$name, new ChildDefinition('security.firewall.guard'))
281+
->replaceArgument(2, new Reference('security.firewall.guard.'.$name.'locator'))
282+
->replaceArgument(3, $name)
283+
->addTag('kernel.event_listener', ['event' => KernelEvents::REQUEST])
284+
;
272285
}
273286
$container
274287
->getDefinition($authenticationManagerId)
@@ -498,7 +511,7 @@ private function createAuthenticationListeners(ContainerBuilder $container, stri
498511
list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint);
499512

500513
$listeners[] = new Reference($listenerId);
501-
$authenticationProviders[] = $provider;
514+
$authenticationProviders[$id.'_'.$key] = $provider;
502515
}
503516
$hasListeners = true;
504517
}
+58Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\SecurityBundle\EventListener;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\DependencyInjection\ServiceLocator;
16+
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
18+
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
19+
use Symfony\Component\Security\Http\Firewall\GuardManagerListener;
20+
21+
/**
22+
* @author Wouter de Jong <wouter@wouterj.nl>
23+
*/
24+
class LazyGuardManagerListener extends GuardManagerListener
25+
{
26+
private $guardLocator;
27+
28+
public function __construct(
29+
AuthenticationManagerInterface $authenticationManager,
30+
GuardAuthenticatorHandler $guardHandler,
31+
ServiceLocator $guardLocator,
32+
string $providerKey,
33+
?LoggerInterface $logger = null
34+
) {
35+
parent::__construct($authenticationManager, $guardHandler, [], $providerKey, $logger);
36+
37+
$this->guardLocator = $guardLocator;
38+
}
39+
40+
protected function getSupportingGuardAuthenticators(Request $request): array
41+
{
42+
$guardAuthenticators = [];
43+
foreach ($this->guardLocator->getProvidedServices() as $key => $type) {
44+
$guardAuthenticator = $this->guardLocator->get($key);
45+
if (null !== $this->logger) {
46+
$this->logger->debug('Checking support on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
47+
}
48+
49+
if ($guardAuthenticator->supports($request)) {
50+
$guardAuthenticators[$key] = $guardAuthenticator;
51+
} elseif (null !== $this->logger) {
52+
$this->logger->debug('Guard authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
53+
}
54+
}
55+
56+
return $guardAuthenticators;
57+
}
58+
}

‎src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/authenticators.xml
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@
44
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
55

66
<services>
7+
<service id="security.firewall.guard.locator"
8+
class="Symfony\Component\DependencyInjection\ServiceLocator"
9+
abstract="true" />
10+
11+
<service id="security.firewall.guard"
12+
class="Symfony\Bundle\SecurityBundle\EventListener\LazyGuardManagerListener"
13+
abstract="true">
14+
<tag name="monolog.logger" channel="security" />
15+
<argument type="service" id="security.authentication.manager"/>
16+
<argument type="service" id="security.authentication.guard_handler"/>
17+
<argument/> <!-- guard authenticator locator -->
18+
<argument/> <!-- provider key -->
19+
<argument type="service" id="logger" on-invalid="null" />
20+
</service>
21+
722
<service id="security.authenticator.http_basic"
823
class="Symfony\Component\Security\Core\Authentication\Authenticator\HttpBasicAuthenticator"
924
abstract="true">

‎src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+8-120Lines changed: 8 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
*/
3535
class GuardAuthenticationListener extends AbstractListener
3636
{
37+
use GuardAuthenticatorListenerTrait;
38+
3739
private $guardHandler;
3840
private $authenticationManager;
3941
private $providerKey;
@@ -73,20 +75,7 @@ public function supports(Request $request): ?bool
7375
$this->logger->debug('Checking for guard authentication credentials.', $context);
7476
}
7577

76-
$guardAuthenticators = [];
77-
78-
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
79-
if (null !== $this->logger) {
80-
$this->logger->debug('Checking support on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
81-
}
82-
83-
if ($guardAuthenticator->supports($request)) {
84-
$guardAuthenticators[$key] = $guardAuthenticator;
85-
} elseif (null !== $this->logger) {
86-
$this->logger->debug('Guard authenticator does not support the request.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
87-
}
88-
}
89-
78+
$guardAuthenticators = $this->getSupportingGuardAuthenticators($request);
9079
if (!$guardAuthenticators) {
9180
return false;
9281
}
@@ -105,86 +94,7 @@ public function authenticate(RequestEvent $event)
10594
$guardAuthenticators = $request->attributes->get('_guard_authenticators');
10695
$request->attributes->remove('_guard_authenticators');
10796

108-
foreach ($guardAuthenticators as $key => $guardAuthenticator) {
109-
// get a key that's unique to *this* guard authenticator
110-
// this MUST be the same as GuardAuthenticationProvider
111-
$uniqueGuardKey = $this->providerKey.'_'.$key;
112-
113-
$this->executeGuardAuthenticator($uniqueGuardKey, $guardAuthenticator, $event);
114-
115-
if ($event->hasResponse()) {
116-
if (null !== $this->logger) {
117-
$this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', ['authenticator' => \get_class($guardAuthenticator)]);
118-
}
119-
120-
break;
121-
}
122-
}
123-
}
124-
125-
private function executeGuardAuthenticator(string $uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, RequestEvent $event)
126-
{
127-
$request = $event->getRequest();
128-
try {
129-
if (null !== $this->logger) {
130-
$this->logger->debug('Calling getCredentials() on guard authenticator.', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
131-
}
132-
133-
// allow the authenticator to fetch authentication info from the request
134-
$credentials = $guardAuthenticator->getCredentials($request);
135-
136-
if (null === $credentials) {
137-
throw new \UnexpectedValueException(sprintf('The return value of "%1$s::getCredentials()" must not be null. Return false from "%1$s::supports()" instead.', get_debug_type($guardAuthenticator)));
138-
}
139-
140-
// create a token with the unique key, so that the provider knows which authenticator to use
141-
$token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey);
142-
143-
if (null !== $this->logger) {
144-
$this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]);
145-
}
146-
// pass the token into the AuthenticationManager system
147-
// this indirectly calls GuardAuthenticationProvider::authenticate()
148-
$token = $this->authenticationManager->authenticate($token);
149-
150-
if (null !== $this->logger) {
151-
$this->logger->info('Guard authentication successful!', ['token' => $token, 'authenticator' => \get_class($guardAuthenticator)]);
152-
}
153-
154-
// sets the token on the token storage, etc
155-
$this->guardHandler->authenticateWithToken($token, $request, $this->providerKey);
156-
} catch (AuthenticationException $e) {
157-
// oh no! Authentication failed!
158-
159-
if (null !== $this->logger) {
160-
$this->logger->info('Guard authentication failed.', ['exception' => $e, 'authenticator' => \get_class($guardAuthenticator)]);
161-
}
162-
163-
$response = $this->guardHandler->handleAuthenticationFailure($e, $request, $guardAuthenticator, $this->providerKey);
164-
165-
if ($response instanceof Response) {
166-
$event->setResponse($response);
167-
}
168-
169-
return;
170-
}
171-
172-
// success!
173-
$response = $this->guardHandler->handleAuthenticationSuccess($token, $request, $guardAuthenticator, $this->providerKey);
174-
if ($response instanceof Response) {
175-
if (null !== $this->logger) {
176-
$this->logger->debug('Guard authenticator set success response.', ['response' => $response, 'authenticator' => \get_class($guardAuthenticator)]);
177-
}
178-
179-
$event->setResponse($response);
180-
} else {
181-
if (null !== $this->logger) {
182-
$this->logger->debug('Guard authenticator set no success response: request continues.', ['authenticator' => \get_class($guardAuthenticator)]);
183-
}
184-
}
185-
186-
// attempt to trigger the remember me functionality
187-
$this->triggerRememberMe($guardAuthenticator, $request, $token, $response);
97+
$this->executeGuardAuthenticators($guardAuthenticators, $event);
18898
}
18999

190100
/**
@@ -195,32 +105,10 @@ public function setRememberMeServices(RememberMeServicesInterface $rememberMeSer
195105
$this->rememberMeServices = $rememberMeServices;
196106
}
197107

198-
/**
199-
* Checks to see if remember me is supported in the authenticator and
200-
* on the firewall. If it is, the RememberMeServicesInterface is notified.
201-
*/
202-
private function triggerRememberMe(AuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null)
108+
protected function getGuardKey(string $key): string
203109
{
204-
if (null === $this->rememberMeServices) {
205-
if (null !== $this->logger) {
206-
$this->logger->debug('Remember me skipped: it is not configured for the firewall.', ['authenticator' => \get_class($guardAuthenticator)]);
207-
}
208-
209-
return;
210-
}
211-
212-
if (!$guardAuthenticator->supportsRememberMe()) {
213-
if (null !== $this->logger) {
214-
$this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($guardAuthenticator)]);
215-
}
216-
217-
return;
218-
}
219-
220-
if (!$response instanceof Response) {
221-
throw new \LogicException(sprintf('"%s::onAuthenticationSuccess()" *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.', get_debug_type($guardAuthenticator)));
222-
}
223-
224-
$this->rememberMeServices->loginSuccess($request, $response, $token);
110+
// get a key that's unique to *this* guard authenticator
111+
// this MUST be the same as GuardAuthenticationProvider
112+
return $this->providerKey.'_'.$key;
225113
}
226114
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.