好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

代码实现方式

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

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);

     };

}

}

配置实现方式

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

?

1

2

3

4

5

6

7

8

9

spring:

   cloud:

     gateway:

       globalcors:

         corsConfigurations:

           '[/**]' :

             allowedOrigins: "*"

             allowedMethods: "*"

             allowedHeaders: "*"

springcloud gateway 跨域的解决

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

验证

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

1、gateway跨域配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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

向容器中注入跨域过滤器

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

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、实现一个过滤器,来做跨域允许

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

?

1

2

3

4

5

# 这个为请求头中的 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添加跨域响应头

?

1

2

3

4

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中方案,测试完美解决!

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

原文链接:https://wanghq.blog.csdn.net/article/details/88179626

查看更多关于spring cloud gateway跨域全局CORS配置方式的详细内容...

  阅读:18次