前提・実現したいこと
サーバサイド: Spring Boot
フロントエンド: Angular5
CORSを使って、ログイン後のリクエストのフィルタリングを行おうとしています。
ログイン処理は完了しており、サーバサイドで発行されたトークンをリクエストヘッダに張り付けてリクエストを行おうとしています。
その際、以下の通りエラーが発生してしまいました。解決方法をご教授よろしくお願いします。
発生している問題・エラーメッセージ
リクエストヘッダに
content-type: application/json
x-xsrf-token: [サーバサイドで発行されたトークン]
を加えて送っているため、プレフライトが実行されます。
その際、以下のようなエラーになります。
Failed to load http://localhost:8080/v1/templates: Response for preflight has invalid HTTP status code 403.
該当のソースコード
以下が SecurityConfig のソースです。
java
1@Configuration 2@EnableWebSecurity 3public class SecurityConfig extends WebSecurityConfigurerAdapter{ 4 5 @Override 6 protected void configure(HttpSecurity http) throws Exception { 7 RequestMatcher csrfRequestMatcher = new RequestMatcher() { 8 // CSRFのチェックをしないURL 9 private AntPathRequestMatcher[] requestMatchers = { 10 new AntPathRequestMatcher("/v1/login/**") 11 }; 12 13 @Override 14 public boolean matches(HttpServletRequest request) { 15 for (AntPathRequestMatcher rm : requestMatchers) { 16 if (rm.matches(request)) { 17 return false; 18 } 19 } 20 return true; 21 } 22 }; 23 24 // ログインしなくてもアクセスできるURL 25 http.authorizeRequests() 26 .antMatchers("/v1/login") 27 .permitAll() 28 .anyRequest().authenticated() //上記にマッチしなければ未認証の場合エラー 29 .and() 30 .csrf() 31 .requireCsrfProtectionMatcher(csrfRequestMatcher) 32 .csrfTokenRepository(this.csrfTokenRepository()); 33 34 http.logout() 35 .logoutUrl("/v1/logout") 36 .permitAll(); 37 } 38 39 40 private CsrfTokenRepository csrfTokenRepository() { 41 HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 42 repository.setHeaderName("X-XSRF-TOKEN"); 43 return repository; 44 } 45}
以下がフィルターの設定を行っている Java のソースです。
Java
1@Component 2public class SimpleCORSFilter implements Filter { 3 4 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 5 HttpServletResponse response = (HttpServletResponse) res; 6 response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200"); 7 response.addHeader("Access-Control-Allow-Credentials", "true"); 8 response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); 9 response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With, X-XSRF-TOKEN"); 10 if ("OPTIONS".equals(request.getMethod())) { 11 return; 12 } 13 chain.doFilter(req, res); 14 } 15 16 public void init(FilterConfig filterConfig) {} 17 18 public void destroy() {} 19 20}
以下がリクエスト送信部分です。
TypeScript
1this.http.get(this.hostname + 'templates', { withCredentials: true, headers: this.headers }).subscribe( 2 json => { 3 this.templates = json; 4 }, 5 error => { 6 console.log(error); 7 } 8 );
試したこと
- csrf を disable にしました。
エラー内容を見る限り、cors のフィルターと関係ない部分で拒否されていると考え、csrf を disable にしてみましたが、結果に変化はありませんでした。
- Chrome のアプリケーション「ARC」を使って確認しました。
ARCを使ってリクエストを送信したところ、通信に成功しました。ARC を使ったリクエストはプレフライトが行われていないので成功したのだと考えられます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。