diff --git a/core/core.services.yml b/core/core.services.yml index 046e04c..0948f59 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -539,6 +539,8 @@ services: class: Zend\Feed\Writer\Extension\WellFormedWeb\Renderer\Entry authentication: class: Drupal\Core\Authentication\AuthenticationManager + calls: + - [setContainer, ['@service_container']] authentication.cookie: class: Drupal\Core\Authentication\Provider\Cookie tags: diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManager.php b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php index ba9fee5..6fb8406 100644 --- a/core/lib/Drupal/Core/Authentication/AuthenticationManager.php +++ b/core/lib/Drupal/Core/Authentication/AuthenticationManager.php @@ -7,6 +7,7 @@ namespace Drupal\Core\Authentication; +use Symfony\Component\DependencyInjection\ContainerAware; use Symfony\Component\HttpFoundation\Request; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -23,28 +24,21 @@ * be responsible. If no provider set an active user then the user is set to * anonymous. */ -class AuthenticationManager implements AuthenticationProviderInterface { +class AuthenticationManager extends ContainerAware implements AuthenticationProviderInterface, AuthenticationManagerInterface { /** - * Array of all registered authentication providers, keyed by ID. + * Array of all registered authentication provider ids and their priorities. * * @var array */ - protected $providers; + protected $providerIds = array(); /** - * Array of all providers and their priority. + * Array of authentication provider objects keyed by provider id. * * @var array */ - protected $providerOrders; - - /** - * Sorted list of registered providers. - * - * @var array - */ - protected $sortedProviders; + protected $providers = array(); /** * Id of the provider that authenticated the user. @@ -58,18 +52,13 @@ class AuthenticationManager implements AuthenticationProviderInterface { * * @param string $provider_id * Identifier of the provider. - * @param \Drupal\Core\Authentication\AuthenticationProviderInterface $provider - * The provider object. * @param int $priority - * The providers priority. + * The provider's priority. */ - public function addProvider($provider_id, AuthenticationProviderInterface $provider, $priority = 0) { + public function addProvider($provider_id, $priority) { $provider_id = substr($provider_id, strlen('authentication.')); - - $this->providers[$provider_id] = $provider; - $this->providerOrders[$priority][$provider_id] = $provider; - // Force the builders to be re-sorted. - $this->sortedProviders = NULL; + $this->providerIds[$provider_id] = $priority; + arsort($this->providerIds); } /** @@ -87,8 +76,13 @@ public function authenticate(Request $request) { $account = NULL; - // Iterate the availlable providers. - foreach ($this->getSortedProviders() as $provider_id => $provider) { + // Iterate the available providers. + foreach (array_keys($this->providerIds) as $provider_id) { + if (!isset($this->providers[$provider_id])) { + $this->loadProvider($provider_id); + } + + $provider = $this->providers[$provider_id]; if ($provider->applies($request)) { // Try to authenticate with this provider, skipping all others. $account = $provider->authenticate($request); @@ -109,7 +103,7 @@ public function authenticate(Request $request) { } // Save the authenticated account and the provider that supplied it - // for later access. + // for later access. $request->attributes->set('account', $account); $request->attributes->set('_authentication_provider', $this->triggeredProviderId); @@ -130,28 +124,24 @@ public function authenticate(Request $request) { * The ID of the default provider. */ public function defaultProviderId() { - $providers = $this->getSortedProviders(); - $provider_ids = array_keys($providers); + $provider_ids = array_keys($this->providerIds); return end($provider_ids); } /** - * Returns the sorted array of authentication providers. + * Lazy-loads authentication provider services. * - * @return array - * An array of authentication provider objects. + * @param string $provider_id + * The service id of the authentication provider service to load. + * + * @throws \InvalidArgumentException + * If there was no provider with the given id. */ - protected function getSortedProviders() { - if (!isset($this->sortedProviders)) { - // Sort the builders according to priority. - krsort($this->providerOrders); - // Merge nested providers from $this->providers into $this->sortedProviders. - $this->sortedProviders = array(); - foreach ($this->providerOrders as $providers) { - $this->sortedProviders = array_merge($this->sortedProviders, $providers); - } + protected function loadProvider($provider_id) { + if (!in_array($provider_id, $this->providerIds)) { + throw new \InvalidArgumentException(sprintf('No authentication provider has been registered for %s', $provider_id)); } - return $this->sortedProviders; + $this->providers[$provider_id] = $this->container->get("authentication.$provider_id"); } /** @@ -166,7 +156,7 @@ protected function getSortedProviders() { * @see \Drupal\Core\Authentication\Provider\Cookie::cleanup() */ public function cleanup(Request $request) { - if (empty($this->providers[$this->triggeredProviderId])) { + if (!isset($this->providers[$this->triggeredProviderId])) { return; } $this->providers[$this->triggeredProviderId]->cleanup($request); diff --git a/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php b/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php new file mode 100644 index 0000000..b547edd --- /dev/null +++ b/core/lib/Drupal/Core/Authentication/AuthenticationManagerInterface.php @@ -0,0 +1,22 @@ +getDefinition('authentication'); - // Iterate all autentication providers and add them to the manager. + // Iterate all authentication providers and add them to the manager. foreach ($container->findTaggedServiceIds('authentication_provider') as $id => $attributes) { $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; - $matcher->addMethodCall('addProvider', array( - $id, - new Reference($id), - $priority, - )); + $matcher->addMethodCall('addProvider', array($id, $priority)); } } } diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php index f9cf972..5bdf61c 100644 --- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php @@ -23,11 +23,11 @@ class AuthenticationSubscriber implements EventSubscriberInterface { /** - * Authentication manager. + * Authentication provider. * * @var AuthenticationProviderInterface */ - protected $authenticationManager; + protected $authenticationProvider; /** * Keep authentication manager as private variable. @@ -35,8 +35,8 @@ class AuthenticationSubscriber implements EventSubscriberInterface { * @param AuthenticationProviderInterface $authentication_manager * The authentication manager. */ - public function __construct(AuthenticationProviderInterface $authentication_manager) { - $this->authenticationManager = $authentication_manager; + public function __construct(AuthenticationProviderInterface $authentication_provider) { + $this->authenticationProvider = $authentication_provider; } /** @@ -47,7 +47,7 @@ public function __construct(AuthenticationProviderInterface $authentication_mana public function onKernelRequestAuthenticate(GetResponseEvent $event) { if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $request = $event->getRequest(); - $this->authenticationManager->authenticate($request); + $this->authenticationProvider->authenticate($request); } } @@ -59,8 +59,7 @@ public function onKernelRequestAuthenticate(GetResponseEvent $event) { public function onRespond(FilterResponseEvent $event) { if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $request = $event->getRequest(); - - $this->authenticationManager->cleanup($request); + $this->authenticationProvider->cleanup($request); } } @@ -71,7 +70,7 @@ public function onRespond(FilterResponseEvent $event) { */ public function onException(GetResponseForExceptionEvent $event) { if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { - $this->authenticationManager->handleException($event); + $this->authenticationProvider->handleException($event); } } diff --git a/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php index ea2fa13..16b1482 100644 --- a/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php +++ b/core/lib/Drupal/Core/Routing/Enhancer/AuthenticationEnhancer.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Routing\Enhancer; -use Drupal\Core\Authentication\AuthenticationManager; +use Drupal\Core\Authentication\AuthenticationManagerInterface; use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Cmf\Component\Routing\RouteObjectInterface; @@ -17,7 +17,7 @@ * * The authentication system happens before routing, so all authentication * providers will attempt to authorize a user. However, not all routes allow - * all authentication mechanisms. Instead, we check if the used provider is + * all authentication mechanisms. Instead, we check if the used provider is * valid for the matched route and if not, force the user to anonymous. */ class AuthenticationEnhancer implements RouteEnhancerInterface { @@ -27,10 +27,16 @@ class AuthenticationEnhancer implements RouteEnhancerInterface { * * @var \Drupal\Core\Authentication\AuthenticationManager */ - protected $manger; + protected $manager; - function __construct(AuthenticationManager $manager) { - $this->manger = $manager; + /** + * Constructs a AuthenticationEnhancer object. + * + * @param AuthenticationManagerInterface $manager + * The authentication manager. + */ + function __construct(AuthenticationManagerInterface $manager) { + $this->manager = $manager; } /** @@ -41,7 +47,7 @@ public function enhance(array $defaults, Request $request) { if (!empty($auth_provider_triggered)) { $route = isset($defaults[RouteObjectInterface::ROUTE_OBJECT]) ? $defaults[RouteObjectInterface::ROUTE_OBJECT] : NULL; - $auth_providers = ($route && $route->getOption('_auth')) ? $route->getOption('_auth') : array($this->manger->defaultProviderId()); + $auth_providers = ($route && $route->getOption('_auth')) ? $route->getOption('_auth') : array($this->manager->defaultProviderId()); // If the request was authenticated with a non-permitted provider, // force the user back to anonymous. if (!in_array($auth_provider_triggered, $auth_providers)) {