[Security/Http] Adds CSRF protection to the form-login
This commit is contained in:
parent
d22743cf3a
commit
dfd921822a
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Configuration\Builder\NodeBuilder;
|
||||
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
@ -27,6 +28,8 @@ class FormLoginFactory extends AbstractFactory
|
||||
{
|
||||
$this->addOption('username_parameter', '_username');
|
||||
$this->addOption('password_parameter', '_password');
|
||||
$this->addOption('csrf_parameter', '_csrf_token');
|
||||
$this->addOption('csrf_page_id', 'form_login');
|
||||
$this->addOption('post_only', true);
|
||||
}
|
||||
|
||||
@ -40,6 +43,15 @@ class FormLoginFactory extends AbstractFactory
|
||||
return 'form-login';
|
||||
}
|
||||
|
||||
public function addConfiguration(NodeBuilder $builder)
|
||||
{
|
||||
parent::addConfiguration($builder);
|
||||
|
||||
$builder
|
||||
->scalarNode('csrf_provider')->cannotBeEmpty()->end()
|
||||
;
|
||||
}
|
||||
|
||||
protected function getListenerId()
|
||||
{
|
||||
return 'security.authentication.listener.form';
|
||||
@ -57,6 +69,20 @@ class FormLoginFactory extends AbstractFactory
|
||||
return $provider;
|
||||
}
|
||||
|
||||
protected function createListener($container, $id, $config, $userProvider)
|
||||
{
|
||||
$listenerId = parent::createListener($container, $id, $config, $userProvider);
|
||||
|
||||
if (isset($config['csrf_provider'])) {
|
||||
$container
|
||||
->getDefinition($listenerId)
|
||||
->addArgument(new Reference($config['csrf_provider']))
|
||||
;
|
||||
}
|
||||
|
||||
return $listenerId;
|
||||
}
|
||||
|
||||
protected function createEntryPoint($container, $id, $config, $defaultEntryPoint)
|
||||
{
|
||||
$entryPointId = 'security.authentication.form_entry_point.'.$id;
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Security\Core\Exception;
|
||||
|
||||
/**
|
||||
* This exception is thrown when the csrf token is invalid.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class InvalidCsrfTokenException extends AuthenticationException
|
||||
{
|
||||
}
|
@ -11,15 +11,16 @@
|
||||
|
||||
namespace Symfony\Component\Security\Http\Firewall;
|
||||
|
||||
use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
||||
use Symfony\Component\HttpKernel\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||
|
||||
/**
|
||||
* UsernamePasswordFormAuthenticationListener is the default implementation of
|
||||
@ -29,16 +30,22 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
*/
|
||||
class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener
|
||||
{
|
||||
protected $csrfProvider;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null)
|
||||
public function __construct(SecurityContextInterface $securityContext, AuthenticationManagerInterface $authenticationManager, SessionAuthenticationStrategyInterface $sessionStrategy, $providerKey, array $options = array(), AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, LoggerInterface $logger = null, CsrfProviderInterface $csrfProvider = null)
|
||||
{
|
||||
parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $providerKey, array_merge(array(
|
||||
'username_parameter' => '_username',
|
||||
'password_parameter' => '_password',
|
||||
'csrf_parameter' => '_csrf_token',
|
||||
'csrf_page_id' => 'form_login',
|
||||
'post_only' => true,
|
||||
), $options), $successHandler, $failureHandler, $logger);
|
||||
|
||||
$this->csrfProvider = $csrfProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,6 +61,14 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null !== $this->csrfProvider) {
|
||||
$csrfToken = $request->get($this->options['csrf_parameter']);
|
||||
|
||||
if (false === $this->csrfProvider->isTokenValid($this->options['csrf_page_id'], $csrfToken)) {
|
||||
throw new InvalidCsrfTokenException('Invalid CSRF token.');
|
||||
}
|
||||
}
|
||||
|
||||
$username = trim($request->get($this->options['username_parameter']));
|
||||
$password = $request->get($this->options['password_parameter']);
|
||||
|
||||
|
Reference in New Issue
Block a user