前提条件
- Spring SecurityのCSRF対策として、CookieCsrfTokenRepositoryを用いた方法を採用していること
やり方
うまく行かなかったケースについて
本来なら、PostmanでCookieからXSRF-TOKENの値を読みだして、その値を環境変数に設定。
そして、次回のリクエスト送信時に、リクエストヘッダのX-XSRF-TOKENにその環境変数送信するように設定して、前回実行時のクッキーXSRF-TOKENの値を送信する、というやり方をするのが本来かと思います。
ネットでもそのような方法がいくつか紹介されている記事を見ました。
しかし、当方が使用しているPostmanの最新のバージョン(2024/8/23現在)だと、処理後にクッキーを取得して環境変数に入れるところまではうまく行くのですが、その後、リクエストヘッダに環境変数を設定しても、設定した環境変数をうまく読み込んでくれません。
行ったことは、以下のような感じです。
var csrfToken = pm.cookies.get("XSRF-TOKEN");
pm.globals.set("csrf-token", csrfToken);
console.log(pm.globals.get("csrf-token"));
上記のように、設定した値をコンソールに出力すると、確かに、クッキーのXSRF-TOKENの値が出力されていることは確認できました。
var csrfToken = pm.cookies.get("XSRF-TOKEN");
pm.environment.set("csrf-token" ,csrfToken);
console.log(pm.environment.get("csrf-token"));
上記についても同様です。
しかし、上記2つのいずれのケースにおいても、これを実行後に、Headerタブで
Key | Value |
---|---|
X-XSRF-TOKEN | {{csrf-token}} |
と設定しても、サーバー側に飛ばされたリクエストのリクエストヘッダのX-XSRF-TOKENの値は、{{csrf-token}} となってしまい、クッキーのXSRF-TOKENから読みだした値にはなってくれませんでした。
解決法
あまりスマートな方法ではありませんが、テスト用にCSRFトークンを取得するためのコントローラーを用意しました。
srcフォルダ配下だとビルド対象として組み込まれてしまうので、mockフォルダを別途作成して、それをビルドパスとして設定します。ローカル環境でのみ有効なmockを作成する感じです。
eclipseだと、以下のような感じになります。
そして、mockフォルダ配下に、公式サイトで紹介しているような、csrfエンドポイント用のコントローラークラスを作成します。
以下、作成するコントローラーです。
公式サイトからの引用となります。
@RestController
public class CsrfController {
@GetMapping("/csrf")
public CsrfToken csrf(CsrfToken csrfToken) {
return csrfToken;
}
}
これを実行すると、以下のようなJSONが出力されます。
{
"token": "270e0283-b0d6-46fa-a072-0eccf2706609",
"parameterName": "_csrf",
"headerName": "X-XSRF-TOKEN"
}
注意点は、もしログイン認証などでアクセス制御を行ってる場合は、上記エンドポイントは、.requestMatchers("/csrf").permitAll()
の対象とする必要があるということです。
ですので、SecurityConfigにアクセス許可設定を別途する必要があります。
リリース対象のSecurityConfigに設定が残ってしまうのは気持ち悪いですが、上記CsrfControllerはリリース対象には含めないので、まぁ問題ないかなと思います。
そして、上記後、PostmanのPre-request Scriptタブを以下のような感じに設定します。
設定内容は以下の通りです。
console.log("csrf取得");
pm.sendRequest("http://localhost:8080/sample/csrf", function (err,res){
var csrfToken = res.json().token;
pm.environment.set('csrf-token', csrfToken);
console.log("取得したtoken:"+csrfToken);
});
最後に、Postmanのヘッダタブを以下のような感じに設定します。
Key | Value |
---|---|
X-XSRF-TOKEN | {{csrf-token}} |
以上で、Spring SecurityにてCSRF対策済みのAPIにPostmanでアクセスできるようになります。
参考サイト
以下の記事を参考にさせていただきました。