迁移到 Spring Boot 2.0.x 时全局 CORS 配置中断

Posted

技术标签:

【中文标题】迁移到 Spring Boot 2.0.x 时全局 CORS 配置中断【英文标题】:Global CORS configuration breaks when migrating to Spring Boot 2.0.x 【发布时间】:2018-10-15 12:23:09 【问题描述】:

为什么不再发送我的“Access-Control-Allow-Credentials”以响应 Spring Boot 2.0.x(在我的情况下为 2.0.1.RELEASE)下的预检调用 (OPTIONS)?这是我在 Spring Boot 1.5.6 下运行良好的全局 CORS 配置:

@Configuration
public class CorsConfig 

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurerAdapter() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/**")
                    .allowedOrigins(
                        "http://localhost:3000",..)
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD");
        
    ;


我的 pom 依赖项(我在做自己的安全并避免 Spring Security):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

我对 REST 端点的服务调用未能通过预检:

无法加载 http://localhost:8080/api/v5/sec/auth:对预检请求的响应未通过访问控制检查:“Access-Control-Allow-Credentials”标头中的值当请求的凭据模式为“包含”时,响应为“”,必须为“真”。因此不允许访问 Origin 'http://localhost:3000'。

我已验证在 Spring Boot 1.5.6 中确实存在“Access-Control-Allow-Credentials”标头,而在 Spring Boot 2.0.1 中则缺失。

我能找到的所有文档,包括 spring.io here 上的最新文档,都表明我的全局配置仍然正确,尽管 WebMvcConfigurerAdapter 现在似乎已被弃用。


更新:


这里是迁移前后的响应头:

迁移前(Spring Boot 1.5.6):

访问控制允许凭据:true 访问控制允许来源:http://localhost:3000 内容类型:application/json;charset=UTF-8 日期:日,日,星期一 yyyy hh:mm:ss GMT 传输编码:分块 变化:起源

迁移后(Spring Boot 2.0.1 - Access-Control-Allow-Credentials 标头缺失,但其他已更改/添加):

访问控制允许标题:内容类型 Access-Control-Allow-Methods: GET,HEAD,POST Access-Control-Allow-Origin: * 访问控制最大年龄:1800 内容长度:0 日期:日,日,星期一 yyyy hh:mm:ss GMT 变化:起源 变化:访问控制请求方法 变化:访问控制请求标头

【问题讨论】:

【参考方案1】:

Spring 文档和许多示例都缺少这一点,但答案很简单。我刚刚在 CorsRegistry 上看到了 allowCredentials() 方法,并将 .allowCredentials(true) 添加到注册表方法链中,并重新添加了 Access-Control-Allow-Credentials 标头。

另外,我不再使用已弃用的 WebMvcConfigurerAdapter,而是现在实现 WebMvcConfigurer 并覆盖 addCorsMappings() 方法。

@Configuration
public class CorsConfig implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 

        registry.addMapping("/**")
                .allowedOrigins(
                        "http://localhost:3000",..)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                .allowCredentials(true)
        ;
    
    

【讨论】:

就我而言,我将 registry.addMapping("/**") 更改为 registry.addMapping("/" ) 并且效果很好 这是一个很好的答案,比Spring的官方文档更好。 Spring 文档中提到了使用 WebMvcConfigurerAdapter,这是一个坏主意,因为一旦这样做,您的 IDE 就会警告您它已被弃用。 您好我也面临同样的问题,但上述修复对我不起作用。 @sammoussa.ua 如果还有什么我需要调查的,请告诉我。 您需要定义“没用”。你尝试了什么,它是如何失败的,代码等等。考虑发布一个关于这些项目的新问题。【参考方案2】:

如果您使用的是 Spring Boot 2.0.x

CORS 支持默认禁用,只有在设置 management.endpoints.web.cors.allowed-origins 属性后才会启用。以下配置允许来自 example.com 域的 GET 和 POST 调用:

management.endpoints.web.cors.allowed-origins=http://example.com management.endpoints.web.cors.allowed-methods=GET,POST

欲了解更多信息refer

【讨论】:

这仅适用于 Spring Actuators 暴露的管理端点,不适用于应用程序本身。【参考方案3】:

我正在使用 Spring Boot 2.0.2。我有同样的问题,但我使用以下代码来修复它。有人有最好的方法吗?

//    Miss `Access-Control-Allow-Origin` header in response using this bean. 
//    @Bean
//    CorsConfigurationSource corsConfigurationSource() 
//        CorsConfiguration configuration = new CorsConfiguration();
//        configuration.setAllowCredentials(true);
//        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
//        configuration.addAllowedMethod("*");
//        configuration.setAllowedOrigins(this.getAllowedOrigins());
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**", configuration);
//        return source;
//    

    @Bean
    public FilterRegistrationBean<CorsFilter> initCorsFilter() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
        config.addAllowedMethod("*");
        config.setAllowedOrigins(this.getAllowedOrigins());
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    

【讨论】:

【参考方案4】:

第 1 步:Spring 已经有了 CorsFilter,尽管您可以将自己的 CorsFilter 注册为 bean 以提供您自己的配置。

@Bean
public CorsFilter corsFilter() 
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); // Provide list of origins if you want multiple origins
    config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
    config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
    config.setAllowCredentials(true);
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);

第 2 步:使用@CrossOrigin 注释对控制器进行注释。

【讨论】:

这个对我有用。在没有弄乱我的代码的情况下,我只是添加了这个 bean 并在控制器上添加了 @CrossOrigin 以使其工作。谢谢【参考方案5】:

这对我有用(Kotlin):

@Configuration
class CorsConfig : WebMvcConfigurer 
    override fun addCorsMappings(registry: CorsRegistry) 
        registry.addMapping("/**")
    

【讨论】:

以上是关于迁移到 Spring Boot 2.0.x 时全局 CORS 配置中断的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 spring boot 插件 2.0.x 从一个具有不同依赖项的 gradle 项目生成 2 个 jars

迁移到 Spring Boot 2 并使用 Spring Batch 4

从 Spring Boot 1.5.10 迁移到 2.0.0 时无法解析依赖项

迁移到 JDK 11 后 Spring Boot 测试中的 Mockito 错误

将已有的spring app迁移到spring-boot,手动配置spring-boot?

使用spring-boot在多个数据库之间进行数据迁移