spring cloud gateway跨域全局CORS配置方式

 更新时间:2021年07月15日 10:31:30   作者:草宝虫  
这篇文章主要介绍了spring cloud gateway跨域全局CORS配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

在Spring 5 Webflux中,配置CORS,可以通过自定义WebFilter实现:

注:此种写法需真实跨域访问,监控header中才会带相应属性。

代码实现方式

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.http.HttpMethod;
import reactor.core.publisher.Mono;
 
import static org.springframework.web.cors.CorsConfiguration.ALL;
public class XXXApplication{
public static void main(String[] args) {
    SpringApplication.run(XXXApplication.class, args);
}
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
    return (ServerWebExchange ctx, WebFilterChain chain) -> {
        ServerHttpRequest request = ctx.getRequest();
        if (!CorsUtils.isCorsRequest(request)) {
            return chain.filter(ctx);
        }
        HttpHeaders requestHeaders = request.getHeaders();
        ServerHttpResponse response = ctx.getResponse();
        HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
        HttpHeaders headers = response.getHeaders();
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
        headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
        if (requestMethod != null) {
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
        }
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
        headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
        if (request.getMethod() == HttpMethod.OPTIONS) {
            response.setStatusCode(HttpStatus.OK);
            return Mono.empty();
        }
        return chain.filter(ctx);
    };
}
}

配置实现方式

网上还提到一种配置写法,实测好用:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowedHeaders: "*"

springcloud gateway 跨域的解决

springcloud gateway提供的自带的跨域过滤器有问题,前端还是会报跨域。zuul不会有这个问题。调试发现主要是游览器发送嗅探请求(OPTIONS)时,没有返回跨域的响应头,从而游览器报跨域问题。

验证

由于springcloud gateway为webflux与zuul不一样,同一个服务,采用spring内置的跨域过滤器,zuul可以通过而gateway报错。具体配置如下:

1、gateway跨域配置

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            # 允许携带认证信息
            # 允许跨域的源(网站域名/ip),设置*为全部
            # 允许跨域请求里的head字段,设置*为全部
            # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
            # 跨域允许的有效期
            allow-credentials: true
            allowed-origins: '*'
            allowed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
            allowed-methods: '*'
            exposed-headers: Content-Type,Content-Length, Authorization, Accept,X-Requested-With
            max-age: 3600

此配置无效,前端还是会报跨域问题,主要是前端发送OPTIONS请求时没有返回跨域信息

2、zuul网关或者其它微服务servlet

向容器中注入跨域过滤器

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author ZhouChuGang
 * @version 1.0
 * @project langangkj-commonm
 * @date 2020/5/4 12:24
 * @Description 跨域过滤器配置
 */
@Slf4j
@configuration
@ConditionalOnMissingBean(CorsFilter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class CorsFilterConfiguration {

    public CorsFilterConfiguration() {
        log.info("==========注入跨域过滤器=============");
    }

    @Bean("corsFilter")
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        // #允许向该服务器提交请求的URI,*表示全部允许
        config.addAllowedOrigin(CorsConfiguration.ALL);
        // 允许cookies跨域
        config.setAllowCredentials(true);
        // #允许访问的头信息,*表示全部
        config.addAllowedHeader(CorsConfiguration.ALL);
        // 允许提交请求的方法,*表示全部允许
        config.addAllowedMethod(CorsConfiguration.ALL);
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

    @Autowired
    @Qualifier("corsFilter")
    private CorsFilter corsFilter;

    /**
     * 配置跨域过滤器
     */
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilterRegistration() {
        FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(corsFilter);
        registration.addUrlPatterns("/*");
        registration.setName("corsFilter");
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return registration;
    }
}

此方案可以完美解决跨域问题。但是springcloud gateway 不是servlet 规范。

解决方案

1、gateway后面的微服务实现跨域

跨域由网关后面的服务实现。

2、实现一个过滤器,来做跨域允许

需要在响应头中加入以下信息

# 这个为请求头中的 origin
add_header 'Access-Control-Allow-Origin' '$http_origin' ;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;

3、采用nginx做代理,配置跨域响应头。(强烈推荐)

请求先到nginx,nginx再去请求gateway, 由nginx添加跨域响应头

add_header 'Access-Control-Allow-Origin' '$http_origin' ;
add_header 'Access-Control-Allow-Credentials' 'true' ;
add_header 'Access-Control-Allow-Methods' 'PUT,POST,GET,DELETE,OPTIONS' ;
add_header 'Access-Control-Allow-Headers' 'Content-Type,Content-Length,Authorization,Accept,X-Requested-With' ;

这里本人为了方便,采用第3中方案,测试完美解决!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • spring Retryable注解实现重试详解

    spring Retryable注解实现重试详解

    这篇文章主要介绍了spring Retryable注解实现重试详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java中的SynchronousQueue阻塞队列使用代码实例

    Java中的SynchronousQueue阻塞队列使用代码实例

    这篇文章主要介绍了Java中的SynchronousQueue阻塞队列使用代码实例,SynchronousQueue是无缓冲区的阻塞队列,即不能直接向队列中添加数据,会报队列满异常,需要的朋友可以参考下
    2023-12-12
  • SpringBoot实现RBAC权限校验模型的示例

    SpringBoot实现RBAC权限校验模型的示例

    本文主要介绍了SpringBoot实现RBAC权限校验模型的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04
  • java中反射(Reflection)机制举例详解

    java中反射(Reflection)机制举例详解

    Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,这篇文章主要介绍了java中反射(Reflection)机制的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-03-03
  • 使用httpclient无需证书调用https的示例(java调用https)

    使用httpclient无需证书调用https的示例(java调用https)

    这篇文章主要介绍了使用httpclient无需证书调用https的示例(java调用https),需要的朋友可以参考下
    2014-04-04
  • JVM解密之解构类加载与GC垃圾回收机制详解

    JVM解密之解构类加载与GC垃圾回收机制详解

    本文主要介绍了Java虚拟机(JVM)的内存划分、类加载机制以及垃圾回收机制,JVM的内存划分为程序计数器、栈、堆和方法区,类加载机制包括类加载过程、加载器模型和双亲委派模型,垃圾回收机制主要包括标记-清除、标记-复制、标记-整理和分代回收算法
    2025-02-02
  • 10分钟搞定Java并发队列

    10分钟搞定Java并发队列

    这篇文章主要介绍了Java并发队列,对此感兴趣的同学,可以参考下
    2021-04-04
  • 详解Java内部类——匿名内部类

    详解Java内部类——匿名内部类

    这篇文章主要介绍了详解Java 匿名内部类的相关资料,帮助大家更好的理解和学习java 内部类的相关知识,感兴趣的朋友可以了解下
    2020-08-08
  • java正则表达式之Pattern与Matcher类详解

    java正则表达式之Pattern与Matcher类详解

    这篇文章主要给大家介绍了关于java正则表达式之Pattern与Matcher类的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java实现调用第三方相关接口

    Java实现调用第三方相关接口

    最近在做一个项目,需要调用第三方接口,本文主要介绍了Java实现调用第三方相关接口,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09

最新评论