SpringBoot跨域加SpringSecurity就失效( 七 )

可以看到 , Spring Security 使用了这个 comparator 在获取 SecurityFilterChain 的时候来保证 filters 的顺序 , 所以 , 研究这个 comparator 就能知道在 SecurityFilterChain 中的那些 Filter 的顺序是如何的了 。
这个 comparator 的类型是 FilterComparator, 从名字就能看出来是专用于 Filter 比较的类 , 它的实现也并不神秘 , 从构造函数就能猜到是如何实现的:
FilterComparator() {Step order = new Step(INITIAL_ORDER, ORDER_STEP);put(ChannelProcessingFilter.class, order.next());put(ConcurrentSessionFilter.class, order.next());put(WebAsyncManagerIntegrationFilter.class, order.next());put(SecurityContextPersistenceFilter.class, order.next());put(HeaderWriterFilter.class, order.next());put(CorsFilter.class, order.next());// 省略代码}可以看到 CorsFilter 排在了第六位 , 在所有的 Security Filter 之前 , 由此便解决了 preflight request 没有携带认证信息的问题 。
5.3.4 小结引入 Spring Security 之后 , 我们的 CORS 验证实际上是依然运行着的 , 只是因为 preflight request 不会携带认证信息 , 所以无法通过身份验证 。 使用 HttpSecurity.cors 方法会帮助我们在当前的 Spring Context 中找到或创建一个 CorsFilter 并安排在身份验证的 Filter 之前 , 以保证能对 preflight request 正确处理 。
6、总结研究了 Spring 中 CORS 的代码 , 我们了解到了这样一些知识:

  • 实现 WebMvcConfigurer.addCorsMappings 方法来进行的 CORS 配置 , 最后会在 Spring 的 Interceptor 或 Handler 中生效 。
  • 注入 CorsFilter 的方式会让 CORS 验证在 Filter 中生效 。
  • 引入 Spring Security 后 , 需要调用 HttpSecurity.cors 方法以保证 CorsFilter 会在身份验证相关的 Filter 之前执行 。
  • HttpSecurity.cors + WebMvcConfigurer.addCorsMappings 是一种相对低效的方式 , 会导致跨域请求分别在 Filter 和 Interceptor 层各经历一次 CORS 验证 。
  • HttpSecurity.cors + 注册 CorsFilter 与 HttpSecurity.cors + 注册 CorsConfigurationSource 在运行的时候是等效的 。
  • 在 Spring 中 , 没有通过 CORS 验证的请求会得到状态码为 403 的响应 。


推荐阅读