FuelPHPのAjaxでのCSRF対策
AjaxというかJavaScriptでのCSRF対策用のSecurity::js_fetch_token()
メソッドがFuelPHPにはあって、ビューで
<?php
echo Security::js_fetch_token();
?>
とやると、CSRF対策のワンタイムトークンを取得するfuel_csrf_token()
関数がJavaScriptで使えるようになります。
なので、デフォルトではfuel_csrf_token
というキーでトークンをPOSTします。例えば、jQueryだと以下のようなコードになり、
$.post(
'/post/create',
{
content: data,
fuel_csrf_token: fuel_csrf_token()
}
)
…略…
コントローラでは、普通にSecurity::check_token()
メソッドでトークンをチェックすればいいです。
if (! Security::check_token()) {
// トークンエラー
}
POSTじゃない場合も、トークンを抽出して
if (! Security::check_token($token)) {
// トークンエラー
}
のように受け取ったトークンを引数に渡せばOKです。
ところで、Security::js_fetch_token()
メソッドの生成するコードは、以下のようになっています。
<script type="text/javascript">
function fuel_csrf_token()
{
if (document.cookie.length > 0)
{
var c_name = "fuel_csrf_token";
c_start = document.cookie.indexOf(c_name + "=");
if (c_start != -1)
{
c_start = c_start + c_name.length + 1;
c_end = document.cookie.indexOf(";" , c_start);
if (c_end == -1)
{
c_end=document.cookie.length;
}
return unescape(document.cookie.substring(c_start, c_end));
}
}
return "";
}
</script>
Cookieからトークンの値を取得しています。なので、HttpOnlyなCookieだとJavaScriptからはトークンを取得できなくなり使えません。
なんかちょっと微妙なんですが、FuelPHPのCSRF対策のトークンはワンタイムトークンのためAjaxリクエストごとに値が変わります。連続してAjaxリクエストを送る可能性がある場合、他にうまく新しいトークンを取得する方法を思い付きません。
ワンタイムトークンをやめないと無理な気がします。
関連
Date: 2014/12/20