フォームのレンダリングごとに CSRF トークンを生成する方法が Symfony 2 に存在しますか? 私のコントローラーでは、次のようなことを試しました:
$request = $this->get('request');
if ($request->getMethod() != 'POST') {
$csrf = $this->get('form.csrf_provider');
$date= new \DateTime("now");
$this->date = $date->format('Y-m-d H:i:s');
$token = $csrf->generateCsrfToken($this->date);
} elseif($request->getMethod() == "POST") {
$csrf = $this->get('form.csrf_provider');
$token = $csrf->generateCsrfToken($this->date);
}
$form = $this->createFormBuilder()
....
->add('_token','hidden',array(
'data' => $token
))->getForm();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
DO something
}
}
すべての時間は、私の要求の正しいトークン ハッシュにあります。しかし、bindRequest の後、parameters.ini のセキュリティ文字列と isValid メソッドから生成されたデフォルト ハッシュへの変更は、確実に FALSE 応答を返します。何らかの方法で存在しますが、それを調整するにはどうすればよいですか?
編集 アンラベラーの回答に応えて、コントローラーを編集してCSRFプロバイダーを作成しましたが、「CSRFトークンが無効です。フォームを再送信してください」というエラーが表示されます。私の CSRF プロバイダーは次のようになります。
namespace My\Namespace;
use Symfony\Component\HttpFoundation\Session;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
class MyCsrfProvider implements CsrfProviderInterface
{
protected $session;
protected $secret;
protected $datetime;
public function __construct(Session $session, $secret)
{
$this->secret = $secret;
$this->datetime = new \DateTime('now');
$this->session = $session;
}
public function generateCsrfToken($intention)
{
return sha1($this->secret.$intention.$this->datetime->format('YmdHis').$this->getSessionId());
}
public function isCsrfTokenValid($intention, $token)
{
return $token === $this->generateCsrfToken($intention);
}
protected function getSessionId()
{
return $this->session->getId();
}
}
config.yml サービス クラスに追加するよりも:
services:
form.csrf_provider:
class: My\Namespace\MyCsrfProvider
arguments: [ @session, %kernel.secret% ]
そしてコントローラーはこれに変更します:
//any form without _token field
$form = $this->createFormBuilder()
->add('field1')
->add('field2')->getForm()
if ($this->getRequest()->getMethod() == 'POST') {
$request = $this->getRequest();
$form->bindRequest($request);
if ($form->isValid()) {
Do something
return $this->redirect($this->generateUrl('somewhere'));
}
}
私のハッシュで数秒で問題になることはありませんか? 日時形式から秒を削除すると機能しますが、有効期限が 1 分であり、良い解決策ではありません。理由は、時代が変わったからだと思います。