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 验证
DefaultCorsProcessor 则是依照 CORS 标准来实现 , 并在验证失败的时候打印 debug 日志并拒绝请求 。 我们只需要关注一下标准中没有定义的验证失败时的状态码:
protected void rejectRequest(ServerHttpResponse response) throws IOException {response.setStatusCode(HttpStatus.FORBIDDEN);response.getBody().write("Invalid CORS request".getBytes(StandardCharsets.UTF_8));}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SpringBoot常用注解
- 阿里爆款SpringBoot项目实战PDF+源码+视频分享
- 全网最深分析:SpringBoot MVC自动配置失效的原因
- SpringBoot+MyBatis+MySQL读写分离实现
- 从零手写并发框架(四)异步转同步 springboot 整合
- SpringBoot配置数据源及MyBatis分页的要点
- 刷新认知!h2database在springboot中的使用
- 「尝鲜」SpringBoot 快速整合 Swagger3.0
- SpringBoot内置http编码功能为例分析自动配置过程
- SpringBoot扫描不到组件?给你提供几种方案