Spring cloud zuul跨域(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hanjun0612/article/details/89634717

项目背景:

我们有web和大屏,以及移动端,需要访问微服务接口。

然而大屏时自己打开的网页,在网页中通过js调用我的webapi。出现了跨域情况。

原因:

出现这个问题,是由于跨域请求有2次请求。

第一次:options(查看请求可用性,确定请求后端是否支持请求类型)

第二次:才是你的真实请求。(get/post...)

解决方案:(有缺点,详见最后)

PreFilter

/**
 * zuul转发前过滤器
 */
@Component
public class PreFilter extends ZuulFilter {
	public PreFilter() {
		super();
	}

	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}

	@Override
	public int filterOrder() {
		return 0;
	}

	@Override
	public boolean shouldFilter() {
//		return true;

		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		//只过滤OPTIONS 请求
		if(request.getMethod().equals(RequestMethod.OPTIONS.name())){

			return true;
		}
		return false;
	}

	@Override
	public Object run() {

		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		HttpServletResponse response = ctx.getResponse();

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

		String requestUrl = request.getRequestURL().toString();
		String requestUri = request.getRequestURI();
		String zuul = requestUrl.substring(0,requestUrl.indexOf(requestUri)); // zuul根路径
		ctx.addZuulRequestHeader("zuul", zuul);
		//不再路由
		ctx.setSendZuulResponse(false);
		ctx.setResponseStatusCode(200);

		return null;
	}
    
	
	
}

PostFilter

@Component
public class PostFilter extends ZuulFilter {
    protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return -1;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //只过滤OPTIONS 请求
        if(request.getMethod().equals(RequestMethod.OPTIONS.name())){

            return false;
        }
        return true;
    }

    @Override
    public Object run() {
        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);
        return null;
    }
}

解决思路:让options 请求进入过滤后,允许跨域。

缺点:网页端出现了问题。比如说退出和登录需要刷新两边。

终其原因是由于,header被设置了两边。因为过滤器无法分辨网页提交的get/post和跨域请求的第二次get/post

猜你喜欢

转载自blog.csdn.net/hanjun0612/article/details/89634717