PlayFramework Java 2.3.xにおけるCSRFチェックのエラーハンドリング


CSRFエラーハンドリング

PlayFramework JavaでCSRFフィルターを利用していると、
ブラウザにこんな白画面とエラーメッセージが出ることがある。
これを回避するために
オリジナルのエラーハンドリング用のクラスを定義して、
CSRFエラーが起きた際に独自の処理を行わせる。

コントローラ

CSRFフィルタリングを適用したい、ViewにFormを渡す側のActionは以下のようにアノテーションを付加

@AddCSRFToken
public static Result get() {
    return ok(form.render());
}

FormのPOST先、受け入れ側のActionは以下のようにアノテーションを付加

@RequireCSRFCheck(error = OriginalCSRFErrorHandler.class)
public static Result save() {
    // Handle body
    return ok();
}

@RequireCSRFCheckの引数にCSRFエラーハンドリング用のクラスを渡す。

CSRFエラーハンドリング用のクラス 

@RequireCSRFCheckの引数に渡している、
CSRFErrorHandlerクラスを実装した以下のようなクラスを作成する。
ここではpackageをcsrfとする。

app/csrf/OriginalCSRFErrorHandler.java
pacakge csrf;

public class OriginalCSRFErrorHandler extends Results implements CSRFErrorHandler {

    public OriginalCSRFErrorHandler() {
    }

    @Override
    public Result handle(String s) {
        /**
         *  処理
         */
        return null;
    }
}

CSRFエラーハンドリング設定オプション

さいごに、CSRF設定オプションとして、エラーハンドリングを行うクラスをapplication.confに追記しておく。

conf/application.conf
## CSRF setting
csrf.error.handler = "csrf.OriginalCSRFErrorHandler"

補足

CSRF(クロスサイトフォージェリ)ってなんだべ

クロスサイトリクエストフォージェリ (CSRF) は、攻撃者が被害者のブラウザに被害者のセッションを使ったリクエストを行わせるように仕向ける、セキュリティ上の脆弱性です。セッショントークンはすべてのリクエストにおいて送信されるので、攻撃者が被害者のブラウザに代わってリクエストを強制できる場合、攻撃者は被害者に代わってリクエストを行えるということになります。

PlayのCSRF対策

Play はリクエストが CSRF リクエストでないことを検証する複数のメソッドを提供しています。その主要なメカニズムは CSRF トークンです。このトークンは、クエリ文字列、または投稿されたすべてのフォームのボディ部分に配置され、同様にユーザーのセッションにも配置されます。そして、Play はこの双方のトークンが存在し、一致することを検証します。
例えば AJAX を通じて行われるような、ブラウザ以外からのリクエストについて簡易に対策できるよう、Play は以下も提供しています:
X-Requested-With ヘッダが存在する場合、Play はそのリクエストが安全であると見なします。X-Requested-With は jQuery のようないくつかのポピュラーな Javascript ライブラリがリクエストに追加します。
値が nocheck の Csrf-Token ヘッダが存在する場合、または適切な CSRF トークンを含む場合、Play はそのリクエストが安全であると見なします。

つまり、Actionの際にCSRFトークンを発行してFormに渡して、POSTされたときにCSRFトークンの値が正当であるか確かめることでCSRFリクエストじゃないかどうか確かめるわけです。

使う準備とかね

ここの「グローバルCSRFフィルタの適用」を見る