J'utilise Symfony2.0 et FOSUserBundle et souhaite désactiver le jeton csrf sur mon formulaire de connexion.
J'ai désactivé la protection csrf globalement sur mon site Web dans mon config.yml:
framework:
csrf_protection:
enabled: false
Cela fonctionne bien, aucun champ csrf n’a été ajouté à mes formulaires. Toutefois, cela ne s’applique pas au formulaire de connexion. Sur ce formulaire uniquement, j'obtiens une erreur "Invalid CSRF Token" si je n'inclus pas le jeton dans le formulaire avec:
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
Comment puis-je désactiver le jeton CSRF sur le formulaire de connexion?
Si vous accédez simplement à votre fichier security.yml et supprimez le csrf_provider de la directive form_login, vous n'avez pas besoin de mettre à jour la classe d'action ni quoi que ce soit.
Vous pouvez désactiver la protection CSRF dans votre classe de formulaire en définissant 'csrf_protection' => false
dans son tableau d'options:
class LoginType extends AbstractType
{
// ...
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Acme\UserBundle\Entity\User',
'csrf_protection' => false
);
}
// ...
}
Si vous utilisez FormBuilder pour créer votre formulaire à la place d'une classe AbstractType, vous pouvez passer le tableau d'options comme second paramètre de createFormBuilder()
comme ceci:
$form = $this->createFormBuilder($users, array('csrf_protection' => false))
->add( ... )
->getForm();
si vous utilisez FOSUserBundle et que vous souhaitez désactiver la protection CSRF uniquement sur le formulaire de connexion, vous devez suivre quelques étapes.
Étape 1) Créez votre propre ensemble d’utilisateurs et votre fichier de contrôleur de sécurité
Afin de remplacer le SecurityController intégré à FOSUserBundle, vous devez d’abord créer votre propre ensemble d’utilisateurs.
Donc, créez un fichier nommé app/src/{YourApp} /UserBundle/Controller/SecurityController.php Vous devez étendre la classe SecurityController d’origine et copier sur la méthode loginAction.
use FOS\UserBundle\Controller\SecurityController as SecurityControllerOrig;
class SecurityController extends SecurityControllerOrig
{
public function loginAction(Request $request)
{
}
}
Dans la méthode loginAction, commentez ou supprimez ces lignes:
$csrfToken = $this->container->has('form.csrf_provider')
? $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate')
: null;
Assurez-vous ensuite que rien n'est transmis à afficher pour le jeton CSRF:
return $this->renderLogin(array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => false,
));
Étape 2) Désactiver la vérification CSRF dans le pare-feu de Symfony (security.yml)
Assurez-vous de commenter la ligne "csrf_provider:" existante dans security.yml:
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
#csrf_provider: form.csrf_provider
Étape 3) Remplacer le routage pour le contrôleur de sécurité de FOSUserBundle (routing.yml)
Dans routing.yml, commentez ces lignes:
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
options:
expose: true
Ajoutez ces lignes en dessous des lignes commentées:
#Over-ride the SecurityController of the FOSUserBundle:
fos_user_security_login:
path: /login
defaults: { _controller: YourAppUserBundle:Security:login }
methods: [GET]
options:
expose: true
fos_user_security_check:
path: /login_check
defaults: { _controller: FOSUserBundle:Security:check }
methods: [POST]
options:
expose: true
fos_user_security_logout:
path: /logout
defaults: { _controller: FOSUserBundle:Security:logout }
methods: [GET]
options:
expose: true
Remarque 1: Je lui ai seulement demandé d'utiliser la méthode loginAction à partir de votre SecurityController personnalisé. Les deux autres méthodes vont à la classe parente (pas sûr si cela fait une différence).
Note 2: Vous avez besoin de la partie "expose: true"! Sinon, vous obtiendrez une erreur JavaScript du bundle de routage fos js.
Ça devrait le faire!
Je devais outrepasser SecurityController loginAction de FOSUserBundle où le formulaire de connexion est instancié.
J'ai remplacé:
$csrfToken = $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate');
return $this->container->get('templating')->renderResponse('FOSUserBundle:Security:login.html.'.$this->container->getParameter('fos_user.template.engine'), array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => $csrfToken,
));
avec:
return $this->container->get('templating')->renderResponse('FOSUserBundle:Security:login.html.'.$this->container->getParameter('fos_user.template.engine'), array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => false,
));