zuul实现Cors跨域的两种方式:corsFilter、继承ZuulFilter-java教程-PHP中文网

大家都知道spring boot 可以通过@CrossOrigin实现跨域。但是在spring cloud 里,如果要粒度那么细的去控制跨域,这个就太繁琐了,所以一般来说,会在路由zuul里实现。

第一种方式:corsFilter

在zuul服务下添加一个corsFilter实现跨域,实现起来方便。代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Configuration

public class GateWayCorsConfig {

@Bean

public FilterRegistrationBean corsFilter() {

final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

final CorsConfiguration config = new CorsConfiguration();

config.setAllowCredentials(`true`);

config.addAllowedOrigin(`"*"`);

config.addAllowedHeader(`"*"`);

config.addAllowedMethod(`"*"`);

//这个请求头在https中会出现,但是有点问题,下面我会说

//config.addExposedHeader("X-forwared-port, X-forwarded-host");

source.registerCorsConfiguration(`"/**"`, config);

FilterRegistrationBean bean = new FilterRegistrationBean(`new CorsFilter(source));`

bean.setOrder(Ordered.HIGHEST_PRECEDENCE);

return bean;

}

}

经过测试,这样的配置在http的情况下跨域是OK的,但是当我的环境切换的https的情况下就发生了奇怪的问题。说明一下我遇到的问题。
前端 服务A后端服务B 在同一台服务器上,服务A 调用 服务B 时,服务A通过负载均衡进入服务B时:
http时,服务A的请求跨域成功,https时,服务A的请求跨域失败。
也就是端口为443的时候,会被认为跨域失败!!
我一开始对比了请求头,以为是少了ExposedHeader的"X-forwared-port, X-forwarded-host",但是添加后,还是失败。因为急着上线,所以我没有去深入测试到底什么原因引起的https请求跨域失败。(所以如果大家发现我哪里写的不对,请务必通知我,让我也明白为什么失败!谢谢!)

第二种方式:继承ZuulFilter

因为第一种方式在https下失败后,我尝试了用zuulfilter实现cors的方式

一共需要两个filiter:一个pre, 一个post

Pre-Filter:

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

@Component

public class FirstFilter extends ZuulFilter {

private Logger logger = LoggerFactory.getLogger(FirstFilter.class);

@Override

public String filterType() {

/*

pre:可以在请求被路由之前调用

route:在路由请求时候被调用

post:在route和error过滤器之后被调用

error:处理请求时发生错误时被调用

* */

// 前置过滤器

return FilterConstants.PRE_TYPE;

}

@Override

public int filterOrder() {

//// 优先级为0,数字越大,优先级越低

return 0;

}

@Override

public boolean shouldFilter() {

RequestContext ctx = RequestContext.getCurrentContext();

HttpServletRequest request = ctx.getRequest();

//只过滤OPTIONS 请求

if`(request.getMethod().equals(RequestMethod.OPTIONS.name())){`

return true`;`

}

return false`;`

}

@Override

public Object run() {

logger.debug(`"FirstFilter run start"`);

RequestContext ctx = RequestContext.getCurrentContext();

HttpServletResponse response = ctx.getResponse();

HttpServletRequest request = ctx.getRequest();

response.setHeader(`"Access-Control-Allow-Origin",request.getHeader("Origin"`));

response.setHeader(`"Access-Control-Allow-Credentials","true"`);

response.setHeader(`"Access-Control-Allow-Headers","authorization, content-type"`);

response.setHeader(`"Access-Control-Allow-Methods","POST,GET"`);

response.setHeader(`"Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host"`);

response.setHeader(`"Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers"`);

//不再路由

ctx.setSendZuulResponse(`false`);

ctx.setResponseStatusCode(200);

logger.debug(`"FirstFilter run end"`);

return null`;`

}

}

Pre-Filter 用来处理预处理OPTIONS请求,当发现是OPTIONS请求的时候,给出跨域响应头,并且不对其进行zuul路由,直接返回成功(200), 给前端服务允许跨域

    • *

post-Filter :

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

@Component

public class PostFilter extends ZuulFilter {

private Logger logger = LoggerFactory.getLogger(PostFilter.class);

@Override

public String filterType() {

/*

pre:可以在请求被路由之前调用

route:在路由请求时候被调用

post:在route和error过滤器之后被调用

error:处理请求时发生错误时被调用

* */

// 前置过滤器

return FilterConstants.POST_TYPE;

}

@Override

public int filterOrder() {

//// 优先级为0,数字越大,优先级越低

return 2;

}

@Override

public boolean shouldFilter() {

RequestContext ctx = RequestContext.getCurrentContext();

HttpServletRequest request = ctx.getRequest();

//过滤各种POST请求

if`(request.getMethod().equals(RequestMethod.OPTIONS.name())){`

return false`;`

}

return true`;`

}

@Override

public Object run() {

logger.debug(`"PostFilter run start"`);

RequestContext ctx = RequestContext.getCurrentContext();

HttpServletResponse response = ctx.getResponse();

HttpServletRequest request = ctx.getRequest();

response.setHeader(`"Access-Control-Allow-Origin",request.getHeader("Origin"`));

response.setHeader(`"Access-Control-Allow-Credentials","true"`);

response.setHeader(`"Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host"`);

response.setHeader(`"Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers"`);

//允许继续路由

ctx.setSendZuulResponse(`true`);

ctx.setResponseStatusCode(200);

logger.debug(`"PostFilter run end"`);

return null`;`

}

}

Post-Filter 用来处理 预处理OPTIONS以外的请求,对于正常的请求,不但要给出跨域请求头,还需要允许请求进行路由(否则你的请求到这儿就结束啦),然后返回状态码200。(emmmm……这里要不要返回200,我觉得可能还要想一想……)

按照以上方式配置的话,方法一出现的问题,就得到了解决。服务A能够正常请求服务B了

虽然是正常实现了需求,但是感觉还是存在很多疑惑,希望大家看到的话,能给我指出不足。一起讨论!

相关文章:

跨域解决方案一:使用CORS实现跨域_html/css_WEB-ITnose

用CORS实现WebApi Ajax跨域请求的方法

请求跨域解决方法CORS

以上就是zuul实现Cors跨域的两种方式:corsFilter、继承ZuulFilter的详细内容,更多请关注php中文网其它相关文章!


Original url: Access
Created at: 2019-03-26 22:43:37
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论