【Spring Security】解決CORS跨域問題
最後更新日期:2024年08月24日
問題原因
解決方法
方法1.在Spring Security
設定類別下,新增返回CorsConfigurationSource
類別的createCorsConfig
()方法,並加入SecurityFilterChain
類別
/**
* 新增 Cors 設定
* @return CorsConfigurationSource
*/
private CorsConfigurationSource createCorsConfig(){
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:5173")); // 請求來源
config.setAllowedHeaders(List.of("*")); // request header
config.setAllowedMethods(List.of("*")); // http method
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults())
.authorizeHttpRequests(request -> request
.requestMatchers("/hello").authenticated()
.requestMatchers("/", "/register").permitAll()
.anyRequest().denyAll()
)
// 解決跨域問題
.cors(cors -> cors.configurationSource(createCorsConfig()))
.build();
}
方法2.宣告一個返回CorsConfigurationSource
類別為Bean
的方法
/**
* 解決 CORS 問題
* @return CorsConfigurationSource
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:5173")); // 請求來源
configuration.setAllowedHeaders(List.of("*")); // request header
configuration.setAllowedMethods(List.of("*")); // http method
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
新增cors()
方法,增加Spring
提供的CorsFilter
,避免401錯誤
因Spring Security
預期所有的API的request
都有一個授權的token
,因為preflight
不會有攜帶token
,而造成401錯誤(our API expects an authorization token in the OPTIONS request)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults())
.authorizeHttpRequests(request -> request
.requestMatchers("/hello").authenticated()
.requestMatchers("/", "/register").permitAll()
.anyRequest().denyAll()
)
// 關閉Spring Security的授權檢查機制
.cors(Customizer.withDefaults()) // disable this line to reproduce the CORS 401
.build();
}
參考資料: Fixing 401s with CORS Preflights and Spring Security