SpringBoot跨域加SpringSecurity就失效( 四 )

addCorsMappings(registry) 调用的是自己的方法 , 由子类 DelegatingWebMvcConfiguration 通过委托的方式调用到 WebMvcConfigurer.addCorsMappings 方法 , 我们的配置也由此被读取到 。
getCorsConfigurations 是一个 protected 方法 , 是为了在扩展该类时 , 仍然能够直接获取到 CORS 配置 。 而这个方法在这个类里被四个地方调用到 , 这四个调用的地方 , 都是为了注册一个 HandlerMapping 到 Spring 容器中 。 每一个地方都会调用 mapping.setCorsConfigurations 方法来接收 CORS 配置 , 而这个 setCorsConfigurations 方法 , 则由 AbstractHandlerMapping 提供 , CorsConfigurations 也被保存在这个抽象类中 。
到此 , 我们的 CORS 配置借由 AbstractHandlerMapping 被注入到了多个 HandlerMapping 中 , 而这些 HandlerMapping 以 Spring 组件的形式被注册到了 Spring 容器中 , 当请求来临时 , 将会被调用 。
5.2.2 获取 CORS 配置还记得前面关于 Filter 和 Interceptor 那张图吗?当请求来到 Spring Web 时 , 一定会到达 DispatcherServlet 这个唯一的 Servlet 。
在 DispatcherServlet.doDispatch 方法中 , 会调用所有 HandlerMapping.getHandler 方法 。 好巧不巧 , 这个方法又是由 AbstractHandlerMapping 实现的:
@Override@Nullablepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 省略代码if (CorsUtils.isCorsRequest(request)) {CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);executionChain = getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;}在这个方法中 , 关于 CORS 的部分都在这个 if 中 。 我们来看看最后这个 getCorsHandlerExecutionChain 做了什么:
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,HandlerExecutionChain chain, @Nullable CorsConfiguration config) {if (CorsUtils.isPreFlightRequest(request)) {HandlerInterceptor[] interceptors = chain.getInterceptors();chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);}else {chain.addInterceptor(new CorsInterceptor(config));}return chain;}可以看到:

  • 针对 preflight request , 由于不会有对应的 Handler 来处理 , 所以这里就创建了一个 PreFlightHandler 来作为这次请求的 handler 。
  • 对于其他的跨域请求 , 因为会有对应的 handler , 所以就在 handlerExecutionChain 中加入一个 CorsInterceptor 来进行 CORS 验证
这里的 PreFlightHandler 和 CorsInterceptor 都是 AbstractHandlerMapping 的内部类 , 实现几乎一致 , 区别仅仅在于一个是 HttpRequestHandler , 一个是 HandlerInterceptor;它们对 CORS 规则的验证都交由 CorsProcessor 接口完成 , 这里采用了默认实现 DefaultCorsProcessor 。
DefaultCorsProcessor 则是依照 CORS 标准来实现 , 并在验证失败的时候打印 debug 日志并拒绝请求 。 我们只需要关注一下标准中没有定义的验证失败时的状态码:
protected void rejectRequest(ServerHttpResponse response) throws IOException {response.setStatusCode(HttpStatus.FORBIDDEN);response.getBody().write("Invalid CORS request".getBytes(StandardCharsets.UTF_8));}


推荐阅读