web-dev-qa-db-ja.com

ログインフォームでCSRFトークンを無効にする

Symfony2.0とFOSUserBundleを使用しており、ログインフォームでcsrfトークンを無効にしたいと考えています。

Config.ymlのWebサイトでcsrf保護をグローバルに無効にしました:

framework:
    csrf_protection:
        enabled:        false

これはうまく機能しており、フォームにcsrfフィールドが追加されていません。ただし、これはログインフォームには適用されません。このフォームでのみ、フォームにトークンを含めないと、「無効なCSRFトークン」エラーが発生します。

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

ログインフォームでCSRFトークンを無効にするにはどうすればよいですか?

17
fkoessler

Security.ymlファイルに移動し、form_loginディレクティブからcsrf_providerを削除するだけの場合は、アクションクラスなどを更新する必要はありません。

19
Daum

オプション配列に_'csrf_protection' => false_を設定すると、フォームクラスのCSRF保護を無効にできます。

_class LoginType extends AbstractType
{
    // ...

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

    // ...

} 
_

AbstractBuilderクラスの代わりにFormBuilderを使用してフォームを作成する場合は、次のように、createFormBuilder()の2番目のパラメータとしてオプション配列を渡すことができます。

_$form = $this->createFormBuilder($users, array('csrf_protection' => false))
        ->add( ... )
        ->getForm();
_
29
Juan Sosa

fOSUserBundleを使用していて、ログインフォームでのみCSRF保護を無効にしたい場合は、いくつかの手順を実行する必要があります。

ステップ1)独自のユーザーバンドルとセキュリティコントローラーファイルを作成する

FOSUserBundleに組み込まれている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)Symfonyのファイアウォール(security.yml)でCSRFチェックを無効にする

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:カスタムSecurityControllerのloginActionメソッドを使用するように依頼しただけです。他の2つのメソッドは、親クラスに行きます(違いがあるかどうかはわかりません)。

注2:「expose:true」の部分が必要です!そうしないと、fos jsルーティングバンドルからJavaScriptエラーが発生します。

それでうまくいくはずです!

1
Jay Sheth

FOSUserBundleの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,
    ));
0
fkoessler