如何在 Spring Boot + Vue 应用程序中修复损坏的 CORS?
How I can fix broken CORS In Spring Boot + Vue app?
在我的问题中,后端有 Spring 引导应用程序(使用 Spotify API),前端有 Vue 应用程序。我在 localhost:8080 上使用服务器,在 localhost:8081 上使用前端。我想通过 axios 将我的前端连接到我的后端,我尝试了所有方法,但仍然出现 CORS 错误。
当我调用测试 GET 端点 /getList() 时,我得到了
Access to XMLHttpRequest at 'http://localhost:8080/getList' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
当我尝试调用 POST /findTracks() 时,我得到:
Access to XMLHttpRequest at 'http://localhost:8080/findTracks' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
而且我已经尝试了所有方法(如您在下面的代码中所见)。
第一个:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**").allowedHeaders("*").allowedMethods("*");
} //even with .allowedOrgins("http://localhost:8081");
}
然后在控制器中class:
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class SpotifyApiController {
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RequestMapping(value = "/getList", method = RequestMethod.GET)
public List<String> getList() {
ArrayList<String> a = new ArrayList<>();
a.add("dwa");
a.add("trzy");
return a;
}
@RequestMapping(value = "/findTracks",
method = RequestMethod.POST,
consumes = "application/json",
produces = "application/json")
public List<Track> getTracksForTitles(@RequestBody TrackWrapper userTracks, TrackService tracksService, OAuth2Authentication details) {
return tracksService.generateTracksDetails(getActiveToken(details), userTracks);
}
然后在 Vue 中:
import axios from 'axios';
const SERVER_URL = 'http://localhost:8080'
const instance = axios.create({
baseURL: SERVER_URL,
timeout: 1000
});
export default{
findTracksInSpotify:(jsonObject)=>instance.post('/findTracks',{
userTracks: jsonObject.userTracks,
headers:{
'Content-Type': 'application/json',
}
}).then(() => function(data){
return JSON.parse(data)
}),
getList:()=>instance.get('/getList',{
transformResponse:[function(data){
return JSON.parse(data)
}]
}),
}
还有我的 Spring 安全 class 如果需要的话:
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.context.request.RequestContextListener;
@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
public class OAuth2Configuration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated()
.and().logout().logoutSuccessUrl("/").permitAll();
}
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
}
我什至安装了 chrome 扩展程序,但它也不起作用。
你能告诉我我做错了什么吗?
有一个 RestConfiguration corsfilter 示例。您可以将以下 bean 添加到您的代码中:
@CrossOrigin
@Configuration
public class RestConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
我认为您不需要 class CorsConfiguration
。
您也不需要使用 CrossOrigin
和 SpotifyApiController
进行注释。
CORS的配置最好放在安全配置中。类似的东西(在 OAuth2Configuration
中):
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
public class OAuth2Configuration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// The configuration that you needed
// If preflight requests are redirected by OAuth conf, you can try adding:
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// CORS configuration
// This value must be parameterized according to your application needs
final String corsOrigin="http://localhost:8081";
// The idea is to insert the CORS filter before the filter injected by
// the @EnableOAuth2Sso annotation
http.addFilterBefore(new CorsFilter(corsConfigurationSource(corsOrigin)), AbstractPreAuthenticatedProcessingFilter.class);
}
private CorsConfigurationSource corsConfigurationSource(String corsOrigin) {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(corsOrigin));
configuration.setAllowedMethods(Arrays.asList("GET","POST","HEAD","OPTIONS","PUT","PATCH","DELETE"));
configuration.setMaxAge(10L);
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Accept","Access-Control-Request-Method","Access-Control-Request-Headers",
"Accept-Language","Authorization","Content-Type","Request-Name","Request-Surname","Origin","X-Request-AppVersion",
"X-Request-OsVersion", "X-Request-Device", "X-Requested-With"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedOrigins(
Lists.newArrayList("*"));
cors.setAllowedMethods(Lists.newArrayList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
cors.setAllowedHeaders(Lists.newArrayList("*"));
return cors;
}).and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("")
.permitAll().and()
.addFilterBefore(setLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
}
您是否尝试在控制器 class 和存储库 class 上使用 @CrossOrigin(origins="http://localhost:8081")?
同时结合它:尝试在您的主 SpringBoot 应用程序中添加 WebConfigurer Bean class 并使用 @CrossOrigin(origins="http://localhost:8081")
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
System.out.println("here");
registry.addMapping("/**").allowedOrigins("http://localhost:8081").allowedMethods("PUT", "DELETE" )
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);;
}
};
}
请也访问此 link enabling CORS in your application server side 并根据您的配置检查您可以使用哪种 CORS 方法。
在我的问题中,后端有 Spring 引导应用程序(使用 Spotify API),前端有 Vue 应用程序。我在 localhost:8080 上使用服务器,在 localhost:8081 上使用前端。我想通过 axios 将我的前端连接到我的后端,我尝试了所有方法,但仍然出现 CORS 错误。
当我调用测试 GET 端点 /getList() 时,我得到了
Access to XMLHttpRequest at 'http://localhost:8080/getList' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
当我尝试调用 POST /findTracks() 时,我得到:
Access to XMLHttpRequest at 'http://localhost:8080/findTracks' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
而且我已经尝试了所有方法(如您在下面的代码中所见)。
第一个:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**").allowedHeaders("*").allowedMethods("*");
} //even with .allowedOrgins("http://localhost:8081");
}
然后在控制器中class:
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class SpotifyApiController {
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RequestMapping(value = "/getList", method = RequestMethod.GET)
public List<String> getList() {
ArrayList<String> a = new ArrayList<>();
a.add("dwa");
a.add("trzy");
return a;
}
@RequestMapping(value = "/findTracks",
method = RequestMethod.POST,
consumes = "application/json",
produces = "application/json")
public List<Track> getTracksForTitles(@RequestBody TrackWrapper userTracks, TrackService tracksService, OAuth2Authentication details) {
return tracksService.generateTracksDetails(getActiveToken(details), userTracks);
}
然后在 Vue 中:
import axios from 'axios';
const SERVER_URL = 'http://localhost:8080'
const instance = axios.create({
baseURL: SERVER_URL,
timeout: 1000
});
export default{
findTracksInSpotify:(jsonObject)=>instance.post('/findTracks',{
userTracks: jsonObject.userTracks,
headers:{
'Content-Type': 'application/json',
}
}).then(() => function(data){
return JSON.parse(data)
}),
getList:()=>instance.get('/getList',{
transformResponse:[function(data){
return JSON.parse(data)
}]
}),
}
还有我的 Spring 安全 class 如果需要的话:
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.context.request.RequestContextListener;
@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
public class OAuth2Configuration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated()
.and().logout().logoutSuccessUrl("/").permitAll();
}
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
}
我什至安装了 chrome 扩展程序,但它也不起作用。
你能告诉我我做错了什么吗?
有一个 RestConfiguration corsfilter 示例。您可以将以下 bean 添加到您的代码中:
@CrossOrigin
@Configuration
public class RestConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
我认为您不需要 class CorsConfiguration
。
您也不需要使用 CrossOrigin
和 SpotifyApiController
进行注释。
CORS的配置最好放在安全配置中。类似的东西(在 OAuth2Configuration
中):
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
public class OAuth2Configuration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// The configuration that you needed
// If preflight requests are redirected by OAuth conf, you can try adding:
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// CORS configuration
// This value must be parameterized according to your application needs
final String corsOrigin="http://localhost:8081";
// The idea is to insert the CORS filter before the filter injected by
// the @EnableOAuth2Sso annotation
http.addFilterBefore(new CorsFilter(corsConfigurationSource(corsOrigin)), AbstractPreAuthenticatedProcessingFilter.class);
}
private CorsConfigurationSource corsConfigurationSource(String corsOrigin) {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(corsOrigin));
configuration.setAllowedMethods(Arrays.asList("GET","POST","HEAD","OPTIONS","PUT","PATCH","DELETE"));
configuration.setMaxAge(10L);
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Accept","Access-Control-Request-Method","Access-Control-Request-Headers",
"Accept-Language","Authorization","Content-Type","Request-Name","Request-Surname","Origin","X-Request-AppVersion",
"X-Request-OsVersion", "X-Request-Device", "X-Requested-With"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedOrigins(
Lists.newArrayList("*"));
cors.setAllowedMethods(Lists.newArrayList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
cors.setAllowedHeaders(Lists.newArrayList("*"));
return cors;
}).and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("")
.permitAll().and()
.addFilterBefore(setLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
}
您是否尝试在控制器 class 和存储库 class 上使用 @CrossOrigin(origins="http://localhost:8081")?
同时结合它:尝试在您的主 SpringBoot 应用程序中添加 WebConfigurer Bean class 并使用 @CrossOrigin(origins="http://localhost:8081")
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
System.out.println("here");
registry.addMapping("/**").allowedOrigins("http://localhost:8081").allowedMethods("PUT", "DELETE" )
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);;
}
};
}
请也访问此 link enabling CORS in your application server side 并根据您的配置检查您可以使用哪种 CORS 方法。