• 技术文章 >Java >java教程

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

    php是最好的语言php是最好的语言2018-08-03 14:40:39原创9187
    大家都知道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了

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

    相关文章:

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

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

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

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:java spring spring-cloud
    上一篇:ActiveMQ 嵌入到Tomcat:需要掌握三个重要的知识点 下一篇:基于mybatis-plus生成不被覆盖的文件并支持swagger注解
    大前端线上培训班

    相关文章推荐

    • 理解java8中java.util.function.*pojo反射新方法(附代码)• 浅析安卓app和微信授权登录及分享完整对接(代码分享)• 一招教你使用java快速创建Map(代码分享)• 教你一招搞定时序数据库在Spring Boot中的使用• 一文讲解Java中初始化List集合的8种方式(附代码)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网