预检浏览器请求期间的 CORS 问题 [重复]

Posted

技术标签:

【中文标题】预检浏览器请求期间的 CORS 问题 [重复]【英文标题】:CORS Issue during preflight browser request [duplicate] 【发布时间】:2020-09-30 15:01:49 【问题描述】:

在尝试通过 Angular 连接到我的 Rest API 时,我遇到了一个看似相当简单的 CORS 问题:

跨域请求被阻止:同源策略不允许读取位于http://mserverIP:port/apicontext/getsitebyuserid/userId 的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”缺失)。

我的 API 是在 Springboot 中设置的,我已经尝试过以下操作:

    在类和方法级别设置 @CrossOrigin(origins = "*") 注释。还启用了跨源的 GET、POST、OPTIONS 以及所有标题。

    使用以下代码全局设置添加的 CORS 配置:

    httpServletResponse.setHeader("Access-Control-Allow-Origin","*");
    httpServletResponse.setHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS,HEAD");
    
    httpServletResponse.setHeader("Access-Control-Max-Age", "7200");
    httpServletResponse.setHeader("Access-Control-Allow-Headers",
            "Content-Type, X-Requested-With, accept, authorization, Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
    

    尝试通过代理身份验证(使用的身份验证是 JWT)。

这条信息可能很重要:对于未经身份验证的 API,不会发生 CORS 问题,但对于受保护的路由,它会返回 403。即使我没有将身份验证标头设置为 true,受保护的路由也会出现问题。

另外,我之前注意到,在预检期间,它的 2 个标头组合会导致问题。如果我发送 origin:http://localhost:4200 和 Access-Control-Request-Method: GET 它会出错。但是,如果我发送其中一个标题,它就可以工作。在 OPTIONS 请求期间,如果有一个名为 origin 的请求头,则请求失败。如果我从邮递员那里删除来源,它会起作用。

【问题讨论】:

看起来你的 cross 工作不正常。试试这种方式***.com/a/59561352/8403689 @Imranmadbar- 这就像一个魅力。谢谢老哥!! 好吧@Charan 听起来不错,所以你可以在那里投赞成票。 【参考方案1】:

首先,如果您使用的是 Spring Security,那么您可以摆脱类级别的注释并在您的安全配置类中全局处理 CORS 配置,例如:

@Override
protected void configure(HttpSecurity http) throws Exception  
     http.
     cors().and().csrf().disable()
            .authorizeRequests()                                                                
            .antMatchers("/**").permitAll()
            .antMatchers("/login").hasRole("ADMIN")                                      
            .antMatchers("/Signup").hasRole("USER")
            .and()
            .exceptionHandling()
            .accessDeniedPage("/access-denied")
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager(), customUserDetailService));



@Bean   
public CorsConfigurationSource corsConfigurationSource() 
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200")); //or * if you want to allow all 
    configuration.setAllowCredentials(true);
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
    configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
    configuration.setExposedHeaders(Arrays.asList("custom-header1", "custom-header2"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration); 
    return source; 

其次,您不需要 cors 过滤器手动将响应标头添加到每个请求,因为如果您正确配置 cors 配置,springboot 将通过 CorsFilter 自动添加所有必要的标头作为响应。因此,如果您使用带有弹簧安全性的 cors,那么使用提供的过滤器和您的配置会更容易。此外,请确保 springboot 自动配置对您有效,因为使用注释 @EnableWebMvc 将禁用自动配置,在这种情况下,您可能必须使用过滤器来处理 cors。

【讨论】:

正如我在第二点中提到的,我已经在全球范围内添加了 CORS 配置,但问题仍然存在。而且,如果使用这个: antMatchers("/**").permitAll();它只会覆盖所有系统的安全性。 @Charan 您可以根据需要配置弹簧安全性,我只是在示例代码中演示了一个简单的设置,只关注 cors 部分。 @Charan 如果您已经有 glabal 设置。尝试删除类级别配置、您添加的过滤器,并提供正确配置 cors bean 的全局配置,然后重试。另请分享您的全局配置以供分析。

以上是关于预检浏览器请求期间的 CORS 问题 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

CORS:为啥我的浏览器不发送 OPTIONS 预检请求?

浏览器中的 CORS 预检错误,但邮递员请求有效

CORS:预检通过,主请求完成 w/200,但浏览器仍然有 Origin 错误

Mac 浏览器似乎吞下了最初的 CORS XHR 预检请求

如何处理无效的 CORS 预检请求?

CORS 预检响应如何实际缓存在浏览器中?