CSRF対策を行ったログインフォームで、セッションタイムアウトしてからログインを試みると、正しいIDとパスワードを入力しているにもかかわらず、ログインすることができません。CSRFトークンが無効になっているからです。
Spring Securityでの話ですが、CSRFトークンをセッションに保存するやりかたなら、他の実装でも起こるかと思います。
ギョームアプリだと、ログインフォームを開いて放置、のような使い方はまずないので、今まで有耶無耶にしていましたが、ちょっと調べてみました。
結論から言うと「フォームを送信する前にJavaScriptで有効なCSRFトークンを取得する」が正解のようです。
具体的には、サーバー側に、
@RestController
public class CsrfController {
@RequestMapping("/csrf-token")
public CsrfToken csrf(CsrfToken token) {
return token;
}
}
のようなエンドポイントを用意します。
クライアント側では、
$(function() {
$('#login-btn').on('click', function() {
e.preventDefault();
$.ajax({
url: '/csrf',
type: 'GET'
})
.done(function(data) {
$('input[name=_csrf]').val(data.token);
$('#form').submit();
});
});
});
みたいに、ログインボタンがクリックされたらAJAXでCSRFトークンを取得して、フォームのhidden項目にセットしてからログインを試みればいいですね。
動かして試したわけではないですが、公式にもあるやりかたなので、うまく動くはず。