Symfony2を使って、AJAX通信のクライアント側とサーバ側を構築する際に、CSRF(クロスサイトリクエストフォージェリ)を防ぐためのトークンをやりとりする方法。
まずは、クライアント側画面を出力するコントローラでは、csrf_providerをつかって、トークンを生成
DefaultController.php
<?php
class DefaultController extends Controller
{
public function clientAction(Request $request)
{
$token = $this->get('form.csrf_provider')->generateCsrfToken('csrf_token');
return $this->render('HogeFugaBundle:Default:client.html.twig', array(
'csrf_token' => $token
));
}
}
この csrf_token
を、twigテンプレートのなかで、JavaScriptから利用可能なよう、変数にセットする。
client.html.twig
<script type="text/javascript">
var csrf_token = '{{ csrf_token }}';
</script>
で、このトークンを、AJAX通信時にHTTPヘッダーに含めて一緒に送信するわけなんだけど、通信部分全部にこのトークンを使う処理を書くのは面倒なので、AJAX通信の送信イベントに、このトークンの付加処理をバインドする。
client.js
$(window).on('ajaxSend', function(elm, xhr, s) {
xhr.setRequestHeader('X-CSRF-Token', csrf_token);
});
これを、サーバ側で受け取ってバリデーションする。
DefaultController.php
<?php
class DefaultController extends Controller
{
public function serverAction(Request $request)
{
$token = $request->headers->get('X-CSRF-Token');
if (false === $this->get('form.csrf_provider')->isCsrfTokenValid('csrf_token', $token)) {
// エラー処理
}
}
}