解决跨域origin重复问题(未使用nginx): Allow-Origin header contains multiple values... but only one is allowed

Gateway跨域, 出现allowed origin重复问题: The ‘Access-Control-Allow-Origin’ header contains multiple values

现象: 跨域时出现这个情况, Spring Cloud Gateway 2.1.3

浏览器console:

Access to XMLHttpRequest at ‘http://localhost:88/api/sys/login’ from origin ‘http://localhost:8001’ has been blocked by CORS policy: The ‘Access-Control-Allow-Origin’ header contains multiple values ‘http://localhost:8001, http://localhost:8001’, but only one is allowed.

背景:

但是我只设置了一次, 并且没有像网上经常出现的也在nginx又设置了一次的情况. 因为根本没有使用nginx.

以下是我在gateway中的, 用于解决跨域问题的过滤器:

package org.zhangcl.gulimall.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * 解决跨域问题的filter
 */
@Configuration
public class CorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter(){
        // 2. 找到他的实现UrlBased...Source,导包要选择reactive包下的
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 2.2 看源码,发现还需要一个CorsConfiguration, 不是react包的
        org.springframework.web.cors.CorsConfiguration corsConfiguration
                = new org.springframework.web.cors.CorsConfiguration();
        // 3 具体配置在这里
        corsConfiguration.addAllowedHeader("*");        // 允许哪些头进行跨域
        corsConfiguration.addAllowedMethod("*");        // 允许哪些请求方式
        //corsConfiguration.addAllowedOrigin("http://localhost:8001");        // 允许哪些来源的请求
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);    // 是否允许携带Cookie跨域
//        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        // 2.1 任意路径都生效
        source.registerCorsConfiguration("/**", corsConfiguration);
        // 1. 配置跨域的配置信息, 这个可以自己实现这个接口, 但是发现有现成的实现类可以直接用, 这里可以注掉

        return new CorsWebFilter(source);
    }
}

尝试:

  1. 先研究这个问题本身

  2. 网上大多数都是和nginx的allowed origin重复设置的情况

  3. 计划下一步再分别考虑gateway是否和vue本身是否默认已经多存在一层allowed origin了的问题

  4. 读一系列资料, 虽然我没有大多数网友的nginx重复设置allowed origin的情况, 但会不会是无意中重复了某一层别的组件的配置呢? 它不一定是nginx, 但仍然可能是另一种形式的重复. 继续摸索

  5. https://www.jianshu.com/p/a46e62f9ad1c, 场景跟我的相当类似, 并且也提到

    结果发现根源在Webflux上边,由于gateway使用的是webflux,而不是springmvc,所以需要先关闭webflux的cors,再从gateway的filter里边设置cors就行了。

    真的有可能是某些不是nginx的多一层配置的情况!

    但是这哥们没具体讲怎么关闭cors

  6. 针对性检索gateway的官网文档 2.1.x

    Important

    Spring Cloud Gateway is built upon Spring Boot 2.x, Spring WebFlux, and Project Reactor. As a consequence many of the familiar synchronous libraries (Spring Data and Spring Security, for example) and patterns you may not apply when using Spring Cloud Gateway. If you are unfamiliar with these projects we suggest you begin by reading their documentation to familiarize yourself with some of the new concepts before working with Spring Cloud Gateway.

    Important

    Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux. It does not work in a traditional Servlet Container or built as a WAR.

    Route Predicate Factories

    Spring Cloud Gateway matches routes as part of the Spring WebFlux HandlerMapping infrastructure. Spring Cloud Gateway includes many built-in Route Predicate Factories. All of these predicates match on different attributes of the HTTP request. Multiple Route Predicate Factories can be combined and are combined via logical and.

    至少印证了确实gateway是build upon webflux的情况, 接下来主要看怎样关闭这个webflux的cors

  7. 针对检索cors

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k9vKcgCu-1589154051661)(bug 问题-2020.assets/image-20200511060123326.png)]

    This will remove duplicate values of Access-Control-Allow-Credentials and Access-Control-Allow-Origin response headers in cases when both the gateway CORS logic and the downstream add them.

    YES! 就是这个味!

  8. 修改gateway的配置, 增加:

              filters:
                - RewritePath=/api/(?.*), /renren-fast/$\{segment}            
                - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tVgUSS9m-1589154051663)(bug 问题-2020.assets/image-20200511062009863.png)]

    测试:

    • 小插曲, 忘了增加allowed methods导致的 (当时只有一个GET), 只是简单更改配置, 这里不展开

    • 然后是喜闻乐见的200! 成功了!

感悟:

问题始于gateway官方, 但本该止于官方文档的, 但是我绕了一段大圈子! 果然"官方文档是最好的教材"!

你可能感兴趣的:(微服务)