17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SpringSecurityとPOSTで嵌った話

Last updated at Posted at 2019-06-11

SpringSecurityとPOSTで嵌った話

SpringSecurity+SpringBootでRestAPIサーバーを作っていたのですが、
ブラウザからPOSTを投げてみると、GETでは認証OKな状態でも403エラーになってしまう現象にぶつかりました。
結構原因究明に苦労したので、備忘も兼ねて書いておきます。

そもそもなぜ弾かれたか?

SpringSecurityは厳重なCSRF対策を行っており、有効化されている場合にPOSTやPUTと言ったリクエストメソッドに対してトークンを要求するため。
トークンを何らかの方法で取得した上で、HttpRequestのHeaderに詰めてやらないと問答無用に403エラーで弾いてきます。

トークンの取得方法

デフォルトではサーバーサイドにリクエストスコープで保持されるだけなのでクライアントサイドからはログインしていてもトークンは見えません。
手動でクライアントサイドに渡して管理しておくか、設定を切り替えてCookieに入るようにする必要があります。

具体的にはWebSecurityConfigで以下のような形にします。


@Override
	public void configure(HttpSecurity http) throws Exception {
		http.oauth2Login().and().authorizeRequests().antMatchers("/**")
         .authenticated()
         .and() //ここからが問題の部分
         .csrf()
         .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
	}


こうすることで、CookieにXSRF-TOKENという名前でトークンが入ってくるようになります。

トークンを入れてPOSTを投げる

取得したトークンはX-XSRF-TOKENという名前でヘッダに入れます。
Cookieに入っていた時のキー名とは微妙に異なるので注意です。

実際のコードは大体以下のような形になります。
なお、Cookieからの値の取り出しにjs-cookieを使っています。

import Cookie from 'js-cookie';
//中略
        const xsrf = Cookie.get('XSRF-TOKEN');
        const resp = await fetch(url),{
            method: 'POST',
            credentials: 'same-origin',
            headers: {
                "Content-Type": "application/json; charset=utf-8",
                'X-XSRF-TOKEN': xsrf
            },
            body:JSON.stringify(param)
        });

ちなみに、axiosなどライブラリによってはここを自動でやってくれるものがあるそうです。

余談

逆に、外部からWebHookなどのPOSTリクエストを認証無しで受けたい場合は、ignoringの方を使うとうまく行きます。
別途アクセス制御はかけないと危険ですが。

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/css/**", "/image/**", "/js/**").antMatchers(HttpMethod.POST, "/api/outer/**");
	}

まとめ

  • SpringSecurityを使っている場合POSTにはtokenが必要
  • WebSecurityConfigで設定しないとtokenはCookieに乗ってくれない
  • テスト用にRestClientから手動で叩く場合でも同じ手法でOK
17
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?