스프링 부트가 @CrossOrigin을 통해 크로스 도메인을 달성할 수 있다는 것은 누구나 알고 있습니다. 그러나 Spring Cloud에서는 이렇게 세밀하게 도메인 간을 제어하려는 경우 너무 번거롭기 때문에 일반적으로 라우팅 zuul에서 구현됩니다.
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의 경우 도메인 전반에 걸쳐 이 구성은 괜찮으나, 제 환경이 https로 전환되면 이상한 문제가 발생합니다. 내가 겪은 문제를 설명하세요.
프런트엔드 서비스 A와 백엔드 서비스 B가 동일한 서버에 있습니다. 서비스 A가 서비스 B를 호출하면 서비스 A가 로드 밸런싱을 통해 서비스 B에 들어갑니다.
service A의 도메인 간 요청이 성공했지만 https를 사용하는 경우 service A의 도메인 간 요청이 실패합니다.
즉, 포트가 443이면 크로스 도메인 실패로 간주됩니다! ! 처음에 요청 헤더를 비교해서 ExposedHeader의 "X-forwared-port, X-forwarded-host"가 누락된 줄 알았는데 추가 후에도 계속 실패했습니다. 급하게 온라인에 접속했기 때문에 도메인 간 https 요청이 실패한 원인을 자세히 테스트하지 않았습니다. (그래서 제가 작성한 내용에서 잘못된 점을 발견하시면 꼭 알려주시고 왜 실패했는지 알려주세요! 감사합니다!)
@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; } }사전 필터는 전처리 OPTIONS 요청을 처리하는 데 사용됩니다. OPTIONS 요청, 출력에 도메인 간 응답 헤더를 제공하고 zuul 라우팅을 수행하지 않고 성공(200)을 직접 반환하여 프런트 엔드 서비스가 도메인 간
@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을 허용합니다. -필터는 OPTIONS 전처리 이외의 요청을 처리하는 데 사용됩니다. 일반 요청은 도메인 간 요청 헤더를 제공할 뿐만 아니라 요청이 라우팅되도록 허용한 다음(그렇지 않으면 요청이 여기에서 종료됨) 상태 코드 200을 반환해야 합니다. . (으음... 여기서 200을 반환할지 고민해봐야 할 것 같네요...) 위와 같은 방식으로 구성하면, 메소드에서 발생하는 문제는 해결될 것입니다. 서비스 A는 정상적으로 서비스 B를 요청할 수 있습니다요구사항은 정상적으로 충족되었음에도 불구하고 아직 의구심이 많이 드는 부분을 보시고 부족한 점을 지적해 주셨으면 좋겠습니다. 함께 토론해 봅시다! 관련 기사:
교차 도메인 솔루션 1: CORS를 사용하여 cross-domain_html/css_WEB-ITnose 구현
CORS를 사용하여 WebApi Ajax 교차 도메인 요청을 구현하는 방법
위 내용은 Zuul은 corsFilter와 ZuulFilter 상속이라는 두 가지 방법으로 Cors 교차 도메인을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!