今回はSpring Boot + Spring Security環境で、特定のURLのみCSRF対策トークンチェックを行う、または特定のURLのみチェックを行わないように設定する方法を記載します。
そもそも
Spring Securityを入れると自動でCSRFチェックが有効になります。これは大変有難いことなのですが、画面がなくURLを呼び出してもらうだけのAPI(RESTなAPI?)を作成する場合、これがちょっと邪魔になります。
なにせ前画面がないので、わざわざCSRFトークンを取るリクエストを出して、取得できたトークンを、本命のリクエストの”X-CSRF-TOKEN”というヘッダに加えて送信しないといけないのです。確かにセキュリティ上チェックする方が良いのでしょう。2リクエスト出してヘッダーを書き換えないといけないので、簡単なCSRFは防げます。
しかし、作成したいAPIがログイン情報に何も関与しない、誰でも使用可能な機能ならどうでしょうか。もしくは別でアカウント情報をチェックするとか。その場合は特定のURLのみCSRFチェックをOFFにしたい。
それではと、調査したところ…
調べたら出てきました。きっとマニュアルにも記載されているのでしょう。しかし、個人のブログになります。なぜなら見つけられなかったからです!インターネット上の諸先輩方にはいつも感謝しております!!いくらしても感謝し足りません!!!やつあたりです!!!!
この記事が初めに見つかりましたが、バージョンが違うのか自分の環境では構文エラーになりました(動作がおかしかったのかな?忘れました)。
次にこの記事を見つけ、上と合体させて、無事に実現できました。
実装方法の解説
実装方法は、とにかくこうです。すごいシンプルで簡単です。
- ①Spring SecurityのSecurityConfigクラス(@EnableWebMvcSecurity)をいらいます。
- ②CSRF対策のトークンチェックが必要なURL、不要なURLを振り分けるRequestMatcherクラスを用意します。
- ③CSRFの設定に”requireCsrfProtectionMatcher”というメソッドがあるので、こいつに②を設定します。
これだけです。簡単で、影響規模が小さいので解説範囲が狭く済み、かつ、もしかすると必要な人もでてくるかも知れない内容だったので、記事にしたのです。ありがたい限りです。
ソース
アクセスURLで/api/以下のリクエストではトークンチェックを行わないようにしています。実際には自前の、別の認証に通らないとAPIは使用できないようになっています。どっちが面倒かは考えものですが、今回はクライアント側の楽さを優先した格好でしょうか。
/**
* Spring Securityの設定クラス
* @author fujita
*
*/
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* HttpSecurity向け設定
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 他の設定がここらにあるはず
/**
* CSRF適用URL判断クラス
*/
RequestMatcher csrfRequestMatcher = new RequestMatcher() {
private AntPathRequestMatcher disabledRequestMatcher =
new AntPathRequestMatcher("/api/**");
@Override
public boolean matches(HttpServletRequest request) {
// GETならCSRFのチェックはしない
if("GET".equals(request.getMethod()))
return false;
// 特定のURLに該当する場合、CSRFチェックしない
if(disabledRequestMatcher.matches(request))
return false;
return true;
}
};
http.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);
}
}
完全にOFFにする実装以外にも、とりあえずAPIを実装したい場合にも、一時的にOFFにして検証するときに知っていて損はないはずです。あ、その場合は、全体的にOFFにすれば良いだけでした、忘れてください。
ともかく以上です。誰かの役に立ってほしいものです。