2013-03-07 70 views
14

我正在使用Symfony2.0和FOSUserBundle,并且想要在我的登录表单上禁用csrf令牌。在登录表单上禁用CSRF令牌

我在config.yml全局禁止我的网站的CSRF保护:

framework: 
    csrf_protection: 
     enabled:  false 

这是运作良好,不存在跨站请求伪造现场加入到我的形式。 但是,这不适用于登录表单。

<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" /> 

如何禁用登录表单的CSRF令牌:仅在这种形式下,如果我不包括与形式的令牌,我得到一个“无效CSRF令牌”的错误?

+1

你为什么想这样做? – j0k 2013-03-11 08:25:17

+0

因为无论用户在登录页面上坐了多久,我的客户都希望验证登录表单。此外,我个人并不认为CSRF的保护对于这个网站是必要的。 – 2013-03-11 09:41:39

回答

15

如果你只是去你security.yml文件,并删除从form_login指令的csrf_provider,不需要更新动作类或任何东西。

+0

好的,这应该是被接受的答案.. – 2013-03-12 02:32:39

27

你可以通过它的选项阵列设置'csrf_protection' => false在你的窗体类禁用CSRF保护:

class LoginType extends AbstractType 
{ 
    // ... 

    public function getDefaultOptions(array $options) 
    { 
     return array(
      'data_class'  => 'Acme\UserBundle\Entity\User', 
      'csrf_protection' => false 
     ); 
    } 

    // ... 

} 

如果您正在使用FormBuilder创建您的形式代替AbstractType类,你可以通过选项数组作为createFormBuilder()这样的第二个参数:

$form = $this->createFormBuilder($users, array('csrf_protection' => false)) 
     ->add(...) 
     ->getForm(); 
+0

问题是我没有这样的LoginType类。我是否应该扩展Symfony2 LoginType类才能将csrf_protection属性设置为false?没有简单的方法吗? – 2013-03-10 02:06:49

+0

我已经更新了我的答案。希望能帮助到你。 – 2013-03-10 02:48:34

+0

是的,它帮助我意识到我必须查看FOSUserBundle的SecurityController以将csrf设置为false。我发布了自己的答案,但有关如何继续的更多细节。 +1 – 2013-03-11 10:06:40

0

我不得不override FOSUserBundle's SecurityController则loginAction其中登录表单实例化。

我代替:

$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, 
    )); 

有:

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, 
    )); 
1

如果您使用的是FOSUserBundle,并且您希望仅在登录表单上禁用CSRF保护,则需要执行几个步骤。

步骤1)创建自己的用户捆绑&安全控制器的文件

为了过骑内置于FOSU​​serBundle的SecurityController,必须先创建自己的用户捆绑。

因此,创建一个名为app/src目录/ {} YourApp /UserBundle/Controller/SecurityController.php 您应该延长原SecurityController类文件,并通过在loginAction方法

use FOS\UserBundle\Controller\SecurityController as SecurityControllerOrig; 
class SecurityController extends SecurityControllerOrig 
{ 
    public function loginAction(Request $request) 
    { 
    } 
} 

副本中根据loginAction方法,注释掉或删除这些行:

$csrfToken = $this->container->has('form.csrf_provider') 
     ? $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate') 
     : null; 

然后确保没有被传递给查看该CSRF令牌:

return $this->renderLogin(array(
     'last_username' => $lastUsername, 
     'error'   => $error, 
     'csrf_token' => false, 
    )); 

步骤2)禁用CSRF在Symfony的防火墙检查(security.yml)

确保您注释掉现有的 “csrf_provider:” 行中的安全性。阳明:

firewalls: 
     main: 
      pattern: ^/ 
      form_login: 
       provider: fos_userbundle 
       #csrf_provider: form.csrf_provider 

步骤3)覆盖为FOSUserBundle的安全控制器路由(的routing.yml)

在routing.yml中,注释掉这些行:

fos_user_security: 
    resource: "@FOSUserBundle/Resources/config/routing/security.xml" 
    options: 
     expose: true 

添加下面的这些行注释行:

#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 

注意1:我只要求它使用loginAction方法您的自定义SecurityController。其他两种方法转到父类(不知道它是否有所作为)。

注2:您需要“揭露:真”部分!否则,您将从fos js routing软件包中收到JavaScript错误。

这应该做到这一点!