filter java 继承_zuul实现Cors跨域的两种方式:corsFilter、继承ZuulFilter

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

第一种方式:corsFilter

在zuul服务下添加一个corsFilter实现跨域,实现起来方便。代码如下@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:@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 :@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了

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

相关文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值