如何在 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

您也不需要使用 CrossOriginSpotifyApiController 进行注释。

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 方法。