RememberMeFactory.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. class RememberMeFactory implements SecurityFactoryInterface
  16. {
  17. protected $options = array(
  18. 'name' => 'REMEMBERME',
  19. 'lifetime' => 31536000,
  20. 'path' => '/',
  21. 'domain' => null,
  22. 'secure' => false,
  23. 'httponly' => true,
  24. 'always_remember_me' => false,
  25. 'remember_me_parameter' => '_remember_me',
  26. );
  27. public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
  28. {
  29. // authentication provider
  30. $authProviderId = 'security.authentication.provider.rememberme.'.$id;
  31. $container
  32. ->setDefinition($authProviderId, new DefinitionDecorator('security.authentication.provider.rememberme'))
  33. ->replaceArgument(0, new Reference('security.user_checker.'.$id))
  34. ->addArgument($config['secret'])
  35. ->addArgument($id)
  36. ;
  37. // remember me services
  38. if (isset($config['token_provider'])) {
  39. $templateId = 'security.authentication.rememberme.services.persistent';
  40. $rememberMeServicesId = $templateId.'.'.$id;
  41. } else {
  42. $templateId = 'security.authentication.rememberme.services.simplehash';
  43. $rememberMeServicesId = $templateId.'.'.$id;
  44. }
  45. if ($container->hasDefinition('security.logout_listener.'.$id)) {
  46. $container
  47. ->getDefinition('security.logout_listener.'.$id)
  48. ->addMethodCall('addHandler', array(new Reference($rememberMeServicesId)))
  49. ;
  50. }
  51. $rememberMeServices = $container->setDefinition($rememberMeServicesId, new DefinitionDecorator($templateId));
  52. $rememberMeServices->replaceArgument(1, $config['secret']);
  53. $rememberMeServices->replaceArgument(2, $id);
  54. if (isset($config['token_provider'])) {
  55. $rememberMeServices->addMethodCall('setTokenProvider', array(
  56. new Reference($config['token_provider']),
  57. ));
  58. }
  59. // remember-me options
  60. $rememberMeServices->replaceArgument(3, array_intersect_key($config, $this->options));
  61. // attach to remember-me aware listeners
  62. $userProviders = array();
  63. foreach ($container->findTaggedServiceIds('security.remember_me_aware') as $serviceId => $attributes) {
  64. foreach ($attributes as $attribute) {
  65. if (!isset($attribute['id']) || $attribute['id'] !== $id) {
  66. continue;
  67. }
  68. if (!isset($attribute['provider'])) {
  69. throw new \RuntimeException('Each "security.remember_me_aware" tag must have a provider attribute.');
  70. }
  71. $userProviders[] = new Reference($attribute['provider']);
  72. $container
  73. ->getDefinition($serviceId)
  74. ->addMethodCall('setRememberMeServices', array(new Reference($rememberMeServicesId)))
  75. ;
  76. }
  77. }
  78. if ($config['user_providers']) {
  79. $userProviders = array();
  80. foreach ($config['user_providers'] as $providerName) {
  81. $userProviders[] = new Reference('security.user.provider.concrete.'.$providerName);
  82. }
  83. }
  84. if (0 === \count($userProviders)) {
  85. throw new \RuntimeException('You must configure at least one remember-me aware listener (such as form-login) for each firewall that has remember-me enabled.');
  86. }
  87. $rememberMeServices->replaceArgument(0, array_unique($userProviders));
  88. // remember-me listener
  89. $listenerId = 'security.authentication.listener.rememberme.'.$id;
  90. $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.rememberme'));
  91. $listener->replaceArgument(1, new Reference($rememberMeServicesId));
  92. $listener->replaceArgument(5, $config['catch_exceptions']);
  93. return array($authProviderId, $listenerId, $defaultEntryPoint);
  94. }
  95. public function getPosition()
  96. {
  97. return 'remember_me';
  98. }
  99. public function getKey()
  100. {
  101. return 'remember-me';
  102. }
  103. public function addConfiguration(NodeDefinition $node)
  104. {
  105. $node->fixXmlConfig('user_provider');
  106. $builder = $node
  107. ->beforeNormalization()
  108. ->ifTrue(function ($v) { return isset($v['key']); })
  109. ->then(function ($v) {
  110. if (isset($v['secret'])) {
  111. throw new \LogicException('Cannot set both key and secret options for remember_me, use only secret instead.');
  112. }
  113. @trigger_error('remember_me.key is deprecated since Symfony 2.8 and will be removed in 3.0. Use remember_me.secret instead.', E_USER_DEPRECATED);
  114. $v['secret'] = $v['key'];
  115. unset($v['key']);
  116. return $v;
  117. })
  118. ->end()
  119. ->children();
  120. $builder
  121. ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
  122. ->scalarNode('token_provider')->end()
  123. ->arrayNode('user_providers')
  124. ->beforeNormalization()
  125. ->ifString()->then(function ($v) { return array($v); })
  126. ->end()
  127. ->prototype('scalar')->end()
  128. ->end()
  129. ->scalarNode('catch_exceptions')->defaultTrue()->end()
  130. ;
  131. foreach ($this->options as $name => $value) {
  132. if (\is_bool($value)) {
  133. $builder->booleanNode($name)->defaultValue($value);
  134. } else {
  135. $builder->scalarNode($name)->defaultValue($value);
  136. }
  137. }
  138. }
  139. }