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.
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!)
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!