問題復現
Access to XMLHttpRequest at 'http://localhost:8081/login' from origin 'http://localhost:8080' 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+Jwt實現的。剛開始我進行了如下配置:
public class AccessControlAllowOriginFilter implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
.allowedMethods("PUT", "DELETE", "GET", "POST", "OPTIONS")
.allowedOrigins("*")
.exposedHeaders("access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin",
"access-control-max-age",
"X-Frame-Options")
.allowCredentials(true);
}
}
//解決跨域問題。cors 預檢請求放行,讓Spring security 放行所有preflight request(cors 預檢請求)
http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
但是請求還是報錯,這兩種配置確認無效。
解決辦法
在前後端交互的過程中,跨域是最基本的問題,後端可以同意進行跨域處理,前端也可以通過代理進行跨域處理。
我這裏採用的是在後端配置跨域請求。
在查看了Spring Security官方文檔以後找到了正確的跨域請求方法。
Spring Security關於跨域請求的配置
查看完官方文檔以後我進行了如下配置:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");//修改爲添加而不是設置,* 最好改爲實際的需要,我這是非生產配置,所以粗暴了一點
configuration.addAllowedMethod("*");//修改爲添加而不是設置
configuration.addAllowedHeader("*");//這裏很重要,起碼需要允許 Access-Control-Allow-Origin
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
在websecurityconfigure的configure(HttpSecurity http)方法裏面還要加上:
http.cors(Customizer.withDefaults());
至此,跨域請求完美解決。
其實跨域請求在第一次請求時瀏覽器都會先發起一個preflight request,這是要進行如下配置纔可以進行跨域訪問:
//解決跨域問題。cors 預檢請求放行,讓Spring security 放行所有preflight request(cors 預檢請求)
http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
有了這些配置前端就可以進行跨域請求了。