Spring Cross Origin Resource Sharing:预检响应不成功

Posted

技术标签:

【中文标题】Spring Cross Origin Resource Sharing:预检响应不成功【英文标题】:Spring Cross Origin Resource Sharing : Preflight response is not successful 【发布时间】:2020-11-09 23:20:15 【问题描述】:

我在 *** 上看到了很多关于这个主题的其他问题,但没有解决我的问题。

我在localhost 端口8000 上使用SpringBoot 开发了一个rest API。我正在尝试从浏览器的fetch API 向端点发出请求。我还使用以下 bean 启用了 CORS:

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurer() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/api/**")
                    .allowedOrigins("*")
                    .allowedHeaders("GET", "POST", "PUT", "DELETE")
                    .allowCredentials(true)
                    .allowedHeaders("*");
            
        ;
    

这是我的安全配置:

@EnableWebSecurity
@Component
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Autowired private UserService userService;

    public SecurityConfiguration() 
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/api/register", "/h2-console/**").permitAll()
        .antMatchers("/**").authenticated()
        .and().httpBasic();

        http.headers().frameOptions().sameOrigin();
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth
        .userDetailsService(userService)
        .passwordEncoder(passwordEncoder());
    

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    

我仍然收到以下错误,而不是所有这些设置:

Preflight response is not successful
Fetch API cannot load http://localhost:8000/api/register/ due to access control checks.
Failed to load resource: Preflight response is not successful

【问题讨论】:

【参考方案1】:

嗯,我最近尝试了很多配置,都是在网上找到的:) 我的情况略有不同,我将 Kotlin 与 Spring Boot 和 WebFlux 一起使用,但我认为总的来说它也应该与 Java 一起使用。

我发现你必须在 SecurityWebFilterChain 中指定 cors 配置。其他配置(包括官方 Spring Security 文档)不起作用。

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class WebSecurityConfig 
    @Bean
    fun configure(http: ServerHttpSecurity): SecurityWebFilterChain? 
        val config = CorsConfiguration().applyPermitDefaultValues()

        config.maxAge = 8000L
        config.allowCredentials = true
        config.allowedOrigins = listOf("http://localhost:4200")
        config.allowedHeaders = listOf("*")
        config.allowedMethods =
            listOf(HttpMethod.OPTIONS.name, HttpMethod.GET.name, HttpMethod.DELETE.name, HttpMethod.PUT.name)
        config.exposedHeaders = listOf(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)

        val source = UrlBasedCorsConfigurationSource().apply 
            registerCorsConfiguration("/**", config)
        

        http
            .cors 
                it.configurationSource(source)
            
            .authorizeExchange 
                it.pathMatchers("/auth").permitAll()
                it.anyExchange().authenticated()
            
            .oauth2ResourceServer 
                it.jwt()
            

        return http.build()
    

【讨论】:

【参考方案2】:

查看https://www.baeldung.com/spring-security-cors-preflight

使用 Spring Security 时,除非明确提及,否则所有没有有效身份验证令牌的请求都会被阻止。浏览器正在使用options 方法发送请求。根据我的配置,该请求将被阻止。因此,要从安全性中排除 cors,我们需要启用它。

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
    .cors().and()
    ...//

【讨论】:

【参考方案3】:
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;
            )

【讨论】:

【参考方案4】:

尝试将此添加到您的SecurityConfiguration

@Bean
    public CorsConfigurationSource corsConfigurationSource() 
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token", "xsrf-token"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

【讨论】:

感谢您的回答。但是,它仍然给出相同的响应

以上是关于Spring Cross Origin Resource Sharing:预检响应不成功的主要内容,如果未能解决你的问题,请参考以下文章

spring 设置跨域 CORS (Cross Origin Resources Share) 跨域

AngularJS spring security login/logout with Cross-Origin Resource Sharing (CORS)

Flask-Restful解决跨域问题No 'Access-Control-Allow-Origin' header is present on the requested resou

如何修复 JS 控制台中的“Cross-Origin Read Blocking (CORB) blocked cross-origin response”?

Ajax - 跨域请求被阻止 - 'Access-Control-Allow-Origin' 缺失 - Spring Boot

记录一次strict-origin-when-cross-origin的错误