0
3

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 3 years have passed since last update.

Spring SecurityでCors設定をし、ReactからRestAPIを叩くときの対処

Last updated at Posted at 2021-04-09

Spring Bootアプリケーションで作成したRest APIをReactから叩いたときのCorsエラー

サーバーサイドをSpring Boot、クライアントサイドをReactで作成しました。サーバーサイドでホストしているRest APIをReactからリクエストするだけの簡単なアプリケーションだったのですが、ベーシック認証を入れたとたんCORSエラーで引っかかりました。

Access to XMLHttpRequest at 'http://localhost:8080/api/v1/memo/all' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

ただ、解決するまでにかなり時間がかかったので、解決できた際の設定をメモがてら残しておこうと思います。

Spring Boot側の設定

Spring Security用のConfigクラスを宣言して、そこへCors設定用のクラスを用意します。

SecurityConfig.java
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	 @Bean
	    public PasswordEncoder passwordEncoder() {
	        return new BCryptPasswordEncoder();
	    }

	 @Bean
	 CorsConfigurationSource corsConfigurationSource() {
	        CorsConfiguration configuration = new CorsConfiguration();

	        configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));

	        configuration.setAllowedHeaders(List.of("*"));
	        configuration.setAllowedMethods(Arrays.asList("GET","POST", "OPTIONS"));
	        configuration.setAllowCredentials(true);

	        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
	        source.registerCorsConfiguration("/**", configuration);

	        return source;
	    }



	 @Autowired
	    private DataSource dataSource;

	    private static final String USER_SQL = "SELECT文";
	    private static final String ROLE_SQL = "SELECT文";

	    @Override
	    protected void configure(HttpSecurity http) throws Exception {

			http.cors().and()
             .csrf().disable()
             .authorizeRequests()
             .antMatchers(HttpMethod.OPTIONS).permitAll()
             .antMatchers(HttpMethod.GET, "/api/*").hasAnyRole("ADMIN")
             .anyRequest().authenticated()
             .and()
             .httpBasic();
	    }

	    @Override
	    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

	        auth.jdbcAuthentication()
	            .dataSource(dataSource)
	            .usersByUsernameQuery(USER_SQL)
	            .authoritiesByUsernameQuery(ROLE_SQL)
	            .passwordEncoder(passwordEncoder());

	    }
}

corsConfigurationSourceメソッドで、アクセス許可するオリジンURLやメソッドの種類を設定するだけです。

App.js
useEffect(() => {
  const getData = () => {
    var xhr = new XMLHttpRequest();

    xhr.onload = function() {
        console.log('Success: ' + xhr.responseText);
    };
    
    xhr.onerror = function() {
        console.log('Error: '  + xhr.responseText);
    };
    
    xhr.open('GET', 'http://localhost:8080/api/v1/memo/all', true);
    xhr.withCredentials = true;
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.setRequestHeader('Authorization',  'Basic '+ btoa('system:password'));
    xhr.send();
  };
     getData();
    
  }, []);

また、クライアントサイドから送られてきたAuth情報をコンソールなどで見たい場合は、Controllerからリクエストヘッダーで設定できます。

Controller.java
@GetMapping("/api/v1/memo/all")
	public List<Memo> getAllMemos(@RequestHeader("Authorization") String authorization) {...}
0
3
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
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?