GuardAuthenticationFactory.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
  11. use Symfony\Component\Config\Definition\Builder\NodeDefinition;
  12. use Symfony\Component\DependencyInjection\ContainerBuilder;
  13. use Symfony\Component\DependencyInjection\DefinitionDecorator;
  14. use Symfony\Component\DependencyInjection\Reference;
  15. /**
  16. * Configures the "guard" authentication provider key under a firewall.
  17. *
  18. * @author Ryan Weaver <ryan@knpuniversity.com>
  19. */
  20. class GuardAuthenticationFactory implements SecurityFactoryInterface
  21. {
  22. public function getPosition()
  23. {
  24. return 'pre_auth';
  25. }
  26. public function getKey()
  27. {
  28. return 'guard';
  29. }
  30. public function addConfiguration(NodeDefinition $node)
  31. {
  32. $node
  33. ->fixXmlConfig('authenticator')
  34. ->children()
  35. ->scalarNode('provider')
  36. ->info('A key from the "providers" section of your security config, in case your user provider is different than the firewall')
  37. ->end()
  38. ->scalarNode('entry_point')
  39. ->info('A service id (of one of your authenticators) whose start() method should be called when an anonymous user hits a page that requires authentication')
  40. ->defaultValue(null)
  41. ->end()
  42. ->arrayNode('authenticators')
  43. ->info('An array of service ids for all of your "authenticators"')
  44. ->requiresAtLeastOneElement()
  45. ->prototype('scalar')->end()
  46. ->end()
  47. ->end()
  48. ;
  49. }
  50. public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
  51. {
  52. $authenticatorIds = $config['authenticators'];
  53. $authenticatorReferences = array();
  54. foreach ($authenticatorIds as $authenticatorId) {
  55. $authenticatorReferences[] = new Reference($authenticatorId);
  56. }
  57. // configure the GuardAuthenticationFactory to have the dynamic constructor arguments
  58. $providerId = 'security.authentication.provider.guard.'.$id;
  59. $container
  60. ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.guard'))
  61. ->replaceArgument(0, $authenticatorReferences)
  62. ->replaceArgument(1, new Reference($userProvider))
  63. ->replaceArgument(2, $id)
  64. ->replaceArgument(3, new Reference('security.user_checker.'.$id))
  65. ;
  66. // listener
  67. $listenerId = 'security.authentication.listener.guard.'.$id;
  68. $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.guard'));
  69. $listener->replaceArgument(2, $id);
  70. $listener->replaceArgument(3, $authenticatorReferences);
  71. // determine the entryPointId to use
  72. $entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config);
  73. // this is always injected - then the listener decides if it should be used
  74. $container
  75. ->getDefinition($listenerId)
  76. ->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProvider));
  77. return array($providerId, $listenerId, $entryPointId);
  78. }
  79. private function determineEntryPoint($defaultEntryPointId, array $config)
  80. {
  81. if ($defaultEntryPointId) {
  82. // explode if they've configured the entry_point, but there is already one
  83. if ($config['entry_point']) {
  84. throw new \LogicException(sprintf('The guard authentication provider cannot use the "%s" entry_point because another entry point is already configured by another provider! Either remove the other provider or move the entry_point configuration as a root key under your firewall (i.e. at the same level as "guard").', $config['entry_point']));
  85. }
  86. return $defaultEntryPointId;
  87. }
  88. if ($config['entry_point']) {
  89. // if it's configured explicitly, use it!
  90. return $config['entry_point'];
  91. }
  92. $authenticatorIds = $config['authenticators'];
  93. if (1 == \count($authenticatorIds)) {
  94. // if there is only one authenticator, use that as the entry point
  95. return array_shift($authenticatorIds);
  96. }
  97. // we have multiple entry points - we must ask them to configure one
  98. throw new \LogicException(sprintf('Because you have multiple guard authenticators, you need to set the "guard.entry_point" key to one of your authenticators (%s)', implode(', ', $authenticatorIds)));
  99. }
  100. }