Spring Bootで実装した認証付きWeb APIで異なるAPIのレスポンスが返される問題
発生していた問題
- 未ログイン状態で、認証が必要なWebAPI-1にリクエスト
- HTTP 401が返される
- ログイン
- HTTP 200 ログイン成功
- レスポンスボディなし
- WebAPI-2(1とは異なるAPI)を呼び出す
Spring Bootのバージョン
- Spring Boot 1.4.2
- Spring Security 4.1.3
原因
問題が発生するパターンのSpring Securityの設定は概ねこんな感じ。
public class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter { private static final String URL_PATTERN = "xxx"; @Override protected void configure(final HttpSecurity http) throws Exception { http.regexMatcher(URL_PATTERN) .formLogin() .successHandler((req, res, auth) -> res.setStatus(HttpServletResponse.SC_OK)) .failureHandler((req, res, auth) -> res.setStatus(HttpServletResponse.SC_UNAUTHORIZED)) .permitAll(); http.regexMatcher(URL_PATTERN) .exceptionHandling() .authenticationEntryPoint(new Http401AuthenticationEntryPoint("Bearer error=\"invalid_request\"")); http.regexMatcher(URL_PATTERN).csrf().disable(); } }
また、APIは下記のような実装を行っていた。
- 単一URLにPOST
- HTTP Headerによって処理をルーティング
この環境下で、前述の再現手順を行うと、以下のようなことが発生していた。
対応策
Spring Securityの設定でリクエストキャッシュを無効にする。
public class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter { private static final String URL_PATTERN = "xxx"; @Override protected void configure(final HttpSecurity http) throws Exception { http.regexMatcher(URL_PATTERN) .requestCache().requestCache(new NullRequestCache()); } }
参考URL
http://www.sedooe.com/2016/04/rest-authentication-using-spring-security-and-spring-session/