[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;
|
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Configuration\Builder\NodeBuilder;
|
||||||
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
use Symfony\Component\DependencyInjection\DefinitionDecorator;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
@ -27,6 +28,8 @@ class FormLoginFactory extends AbstractFactory
|
|||||||
{
|
{
|
||||||
$this->addOption('username_parameter', '_username');
|
$this->addOption('username_parameter', '_username');
|
||||||
$this->addOption('password_parameter', '_password');
|
$this->addOption('password_parameter', '_password');
|
||||||
|
$this->addOption('csrf_parameter', '_csrf_token');
|
||||||
|
$this->addOption('csrf_page_id', 'form_login');
|
||||||
$this->addOption('post_only', true);
|
$this->addOption('post_only', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +43,15 @@ class FormLoginFactory extends AbstractFactory
|
|||||||
return 'form-login';
|
return 'form-login';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addConfiguration(NodeBuilder $builder)
|
||||||
|
{
|
||||||
|
parent::addConfiguration($builder);
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->scalarNode('csrf_provider')->cannotBeEmpty()->end()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getListenerId()
|
protected function getListenerId()
|
||||||
{
|
{
|
||||||
return 'security.authentication.listener.form';
|
return 'security.authentication.listener.form';
|
||||||
@ -57,6 +69,20 @@ class FormLoginFactory extends AbstractFactory
|
|||||||
return $provider;
|
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)
|
protected function createEntryPoint($container, $id, $config, $defaultEntryPoint)
|
||||||
{
|
{
|
||||||
$entryPointId = 'security.authentication.form_entry_point.'.$id;
|
$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;
|
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\AuthenticationFailureHandlerInterface;
|
||||||
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
|
||||||
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface;
|
||||||
|
|
||||||
use Symfony\Component\Security\Core\SecurityContextInterface;
|
|
||||||
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
|
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\Authentication\Token\UsernamePasswordToken;
|
||||||
|
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||||
|
use Symfony\Component\Security\Core\SecurityContextInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UsernamePasswordFormAuthenticationListener is the default implementation of
|
* UsernamePasswordFormAuthenticationListener is the default implementation of
|
||||||
@ -29,16 +30,22 @@ use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
|||||||
*/
|
*/
|
||||||
class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener
|
class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationListener
|
||||||
{
|
{
|
||||||
|
protected $csrfProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@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(
|
parent::__construct($securityContext, $authenticationManager, $sessionStrategy, $providerKey, array_merge(array(
|
||||||
'username_parameter' => '_username',
|
'username_parameter' => '_username',
|
||||||
'password_parameter' => '_password',
|
'password_parameter' => '_password',
|
||||||
|
'csrf_parameter' => '_csrf_token',
|
||||||
|
'csrf_page_id' => 'form_login',
|
||||||
'post_only' => true,
|
'post_only' => true,
|
||||||
), $options), $successHandler, $failureHandler, $logger);
|
), $options), $successHandler, $failureHandler, $logger);
|
||||||
|
|
||||||
|
$this->csrfProvider = $csrfProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,6 +61,14 @@ class UsernamePasswordFormAuthenticationListener extends AbstractAuthenticationL
|
|||||||
return null;
|
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']));
|
$username = trim($request->get($this->options['username_parameter']));
|
||||||
$password = $request->get($this->options['password_parameter']);
|
$password = $request->get($this->options['password_parameter']);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user