11

Symfony2フォームを作成し、リクエストにバインドしました。フォームの残りの部分に進む前に、CSRFトークンが有効/無効かどうかを明示的に確認する必要があります。

$form['_token']->isValid()OutOfBoundsException「Child_tokenは存在しません」というメッセージとともにスローされます。

レンダリングされたフォームに_tokenフィールドが含まれていることを確認できます。CSRF値が無効な場合、$form->isValid()falseを返します。

ここで何が欠けていますか?


アップデート1:

コントローラー(部分的):

private function buildTestForm() {
    $form = $this->createFormBuilder()
            ->add('name','text')
            ->getForm();
    return $form;
}

/**
 * @Route("/test/show_form", name="test.form.show")
 * @Method("GET")
 */
public function showFormTest()
{
    $form = $this->buildTestForm();
    return $this->render('TestBundle::form_test.html.twig', array('form' => $form->createView()));
}

/**
 * @Route("/test/submit_form", name="test.form.submit")
 * @Method("POST")
 */
public function formTest()
{
    $form = $this->buildTestForm();
    $form->bind($this->getRequest());
    if ($form['_token']->isValid()) {
        return new Response('_token is valid');
    } else {
        return new Response('_token is invalid');
    }
}

レンプレート

{# Twig template #}
<form action="{{ path('test.form.submit') }}" method="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}
    <input type="submit" name="go" value="Test Form" />
</form>
4

4 に答える 4

11

csrfトークンを手動でチェックする文書化された方法はありません。symfonyはこのトークンの存在と正確さを自動的に検証します。http://symfony.com/doc/current/book/forms.html#csrf-protection

ただし、csrfプロバイダーがあります。

http://api.symfony.com/2.0/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.html

http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html

CSRF保護を提供できるクラスをマークするメソッドgenerateCsrfToken()を使用して、CSRFトークンを生成できます。このメソッドには、CSRF攻撃から保護する必要があるページに固有の値を渡す必要があります。この値は必ずしも秘密である必要はありません。このインターフェースの実装は、より多くの秘密情報を追加する責任があります。

CSRF攻撃に対してフォーム送信を保護する場合は、「インテンション」文字列を指定できます。このようにして、フォームを処理するように設計されたページ、つまり、同じインテンション文字列を使用してisCsrfTokenValid()でCSRFトークンを検証するページにのみフォームをバインドできるようにします。

このようにプロバイダーを取得できます

$csrf = $this->get('form.csrf_provider');

その後、使用することができます

public Boolean isCsrfTokenValid(string $intention, string $token)

Validates a CSRF token.

パラメータstring$intentionCSRFトークンを生成するときに使用される意図string$tokenブラウザによって提供されるトークン

戻り値ブール値ブラウザによって提供されたトークンが正しいかどうか

フォームで使用されている意図文字列を見つける必要があります。

SOに関するいくつかの興味深い投稿:

SymfonyCSRFとAjax

Symfony2はCSRFトークンとリンクします

于 2013-02-24T10:49:28.923 に答える
11

アートワーク広告に加えて、意図を指定できます。

小枝:

<form method="post">
    <input type="text" name="form_name[field]" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('form_name', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));

か否か:

小枝:

<form method="post">
    <input type="text" name="field" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));
于 2014-08-28T10:03:04.890 に答える
1

コントローラの外部(リスナーなど)でトークンを検証する別の方法(DIを使用する場合):

/** @var Symfony\Component\Security\Csrf\CsrfTokenManagerInterface */
private $csrfTokenManager;

public function __construct(CsrfTokenManagerInterface $csrfTokenManager) 
{
    $this->csrfTokenManager = $csrfTokenManager;
}

public function isValid(): bool
{
    return $this->csrfTokenManager->isTokenValid(
            new CsrfToken('authenticate', $request->getRequest()->headers->get('X-CSRF-TOKEN'))
        );
}
于 2019-02-14T12:49:06.057 に答える
0

これはわかりませんが、マップされていないフィールドでバリデーターを試しましたか?

$violations = $this->get('validator')->validatePropertyValue($entity, '_token', $form['_token']);
if (count($violations)) {
    // the property value is not valid
}
于 2013-02-24T18:21:03.700 に答える