Home  >  Article  >  Java  >  Zuul implements Cors cross-domain in two ways: corsFilter and inheriting ZuulFilter

Zuul implements Cors cross-domain in two ways: corsFilter and inheriting ZuulFilter

php是最好的语言
php是最好的语言Original
2018-08-03 14:40:3911137browse

Everyone knows that spring boot can achieve cross-domain through @CrossOrigin. But in spring cloud, if you want to control cross-domain with such fine granularity, this is too cumbersome, so generally speaking, it will be implemented in routing zuul.

The first way: corsFilter

Add a corsFilter under the zuul service to achieve cross-domain, which is convenient to implement. The code is as follows

@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;
    }
}

After testing, this configuration is OK across domains in the case of http, but when my environment switches to https, a strange problem occurs. Explain the problem I encountered.
Front-endService A and Back-end service B are on the same server, Service A calls Service B, Service AWhen entering Service B through load balancing: When
http is used, the cross-domain request of Service A is successful. When https is used, the cross-domain request of Service A fails.
That is, when the port is 443, it will be considered a cross-domain failure! !
I compared the request headers at first and thought that the "X-forwared-port, X-forwarded-host" of ExposedHeader was missing, but after adding it, it still failed. Because I was in a hurry to go online, I didn't go in-depth to test what caused the https request to fail cross-domain. (So ​​if you find something wrong with what I wrote, please be sure to inform me and let me understand why it failed! Thank you!)

Second way: inherit ZuulFilter

Because of the first way After failing under https, I tried to use zuulfilter to implement cors

A total of two filiters are needed: one pre, one 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 is used to process preprocessing OPTIONS requests. When it is found to be an OPTIONS request, a cross-domain response header is given, and it is not routed by zuul, and directly returns success (200), allowing cross-domain to the front-end service


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 is used to process requests other than preprocessing OPTIONS. For normal requests, not only must the cross-domain request header be given, but the request must also be allowed to proceed. Routing (otherwise your request will end here), and then return status code 200. (emmmm... I think I might have to think about whether to return 200 here...)

If configured in the above way, the problems that arise in the method will be solved. Service A can request Service B normally

Although the requirements have been fulfilled normally, I still feel that there are many doubts. I hope that if you see it, you can point out the shortcomings to me. discuss together!

Related articles:

Cross-domain solution one: Use CORS to achieve cross-domain_html/css_WEB-ITnose

Use CORS to implement WebApi Ajax cross-domain request method

The above is the detailed content of Zuul implements Cors cross-domain in two ways: corsFilter and inheriting ZuulFilter. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn