Spring CORS 解决方案深度对比:CorsInterceptor vs CorsFilter

问题

如果在过滤器中直接返回,那么使用addCorsMappings 则不生效。因为时机不同,相当于没有处理跨域拦截之前直接返回了,被认为是非法请求。

一、addCorsMappings的执行时机

addCorsMappings的跨域校验逻辑嵌入在 Spring MVC 的请求处理链中,其核心执行时机如下:

  1. 注册阶段 在应用启动时,通过实现 WebMvcConfigurer 接口并重写 addCorsMappings 方法,将 CORS 配置注册到 CorsRegistry 中。这些配置会被转换为 CorsConfiguration 对象,并关联到 HandlerMapping

  2. 请求处理阶段 当请求进入 DispatcherServletdoDispatch 方法时:

    1. 通过 getHandler() 获取对应的 HandlerExecutionChain(包含目标控制器和拦截器链)8。
    2. HandlerMapping 阶段,系统会根据 URL 匹配规则找到对应的 CORS 配置,并生成 CorsInterceptor 拦截器。
    3. 若请求为 OPTIONS 预检请求,直接生成包含 CORS 响应头的空响应并终止流程;若为简单请求,则在响应中动态添加 CORS 头信息后继续执行后续逻辑

二、关键源码分析

1. addCorsMappings 配置注册

通过 CorsRegistry 将配置存储为 CorsRegistration 对象,最终生成 CorsConfiguration

typescript 复制代码
 // WebMvcConfigurer 实现类中的配置 @Override  
public void addCorsMappings(CorsRegistry registry) {    
registry.addMapping("/**")            
.allowedOrigins("*")            
.allowedMethods("GET", "POST");  
}  

// 源码:CorsRegistry 内部存储逻辑
public CorsRegistration addMapping(String pathPattern) {  CorsRegistration registration = new CorsRegistration(pathPattern);  this.registrations.add(registration);  return registration;  
}

配置最终被关联到 HandlerMappingCorsConfigurationSource


  1. 请求处理流程(DispatcherServlet 类)

doDispatch 方法中,通过 HandlerMapping 获取处理器链时触发跨域校验:

scss 复制代码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {  
// 1. 获取处理器执行链
HandlerExecutionChain mappedHandler = getHandler(processedRequest);  
// 2. 检查 CORS 预检请求
if (mappedHandler != null) {       
 HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();  
 for (HandlerInterceptor interceptor : interceptors) { 
  if (interceptor instanceof CorsInterceptor) {  
  // 执行跨域校验逻辑
  boolean isValid = ((CorsInterceptor) interceptor).preHandle(...);  
  if (!isValid) return;            
  }        
  }    
  }  
  // 3. 继续执行后续拦截器和控制器
}  

若请求未通过 CORS 校验,直接返回错误响应头(如 403 Forbidden)36。


  1. 跨域响应头注入

CorsInterceptor 中,通过 CorsUtils 工具类处理跨域头信息:

typescript 复制代码
public class CorsInterceptor implements HandlerInterceptor {  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {  // 校验 Origin 并注入响应头
        CorsConfiguration config = getCorsConfiguration(handler);  
        if (config != null) {            
            CorsUtils.processCorsRequest(config, request, response);        
        }  
        return true;
    }  
}  

校验通过后,CorsUtils 会在响应头中写入 Access-Control-Allow-OriginAccess-Control-Allow-Methods 等字段68。


三、执行顺序示意图

scss 复制代码
客户端请求 → DispatcherServlet → getHandler() → HandlerMapping(CORS校验)  
                             ↓  
                  通过校验 → 执行后续拦截器/控制器  
                             ↓  
                  未通过校验 → 返回 CORS 错误响应  

整个过程在 Spring MVC 的处理器映射阶段完成,早于业务拦截器和控制器逻辑36。


总结

addCorsMappings 的跨域校验通过 HandlerMapping 在请求处理链的前置阶段实现,其源码核心逻辑分布在 CorsRegistry 配置注册、DispatcherServletdoDispatch 方法以及 CorsInterceptor 拦截器中


Spring CORS 解决方案深度对比:CorsInterceptor vs CorsFilter

权威解析 + 源码验证(基于 Spring 6.1.9)


一、核心差异对比
‌对比维度‌ ‌CorsInterceptor‌ ‌CorsFilter‌
‌实现层级‌ Spring MVC 拦截器(HandlerInterceptor) Servlet 过滤器(Filter)
‌执行时机‌ 在 HandlerMapping 阶段生效,位于拦截器链中 在 Servlet 容器层生效,优先于所有拦截器和控制器 ‌8
‌配置入口‌ WebMvcConfigurer.addCorsMappings() 手动注册 CorsFilter Bean ‌37
‌依赖框架‌ 仅支持 Spring MVC 应用 支持所有 Servlet 容器(如 Tomcat、Jetty)
‌处理阶段‌ 请求进入 Spring MVC 处理链后 请求进入 Servlet 容器后,Spring MVC 处理链前
‌底层原理‌ 通过 HandlerMapping 动态附加 CORS 响应头 直接操作 HttpServletResponse 写入响应头 ‌8
‌灵活性‌ 仅支持路径级别的全局规则 可自定义复杂逻辑(如动态域名、Header 处理) ‌37
‌官方推荐场景‌ 简单全局配置,无拦截器冲突时使用 需优先处理跨域或存在拦截器冲突时使用 ‌8

三、常见问题与解决方案
‌问题场景‌ ‌根因分析‌ ‌解决方案‌
‌跨域配置被拦截器拦截失效‌ 拦截器先于 CorsInterceptor 执行,未注入响应头 ‌8 改用 CorsFilter 或拦截器中放行 OPTIONS 请求 ‌8
‌DELETE/PUT 请求跨域失败‌ 未正确处理 OPTIONS 预检请求 确保配置包含 allowedMethods("DELETE", "PUT") ‌56
‌Credentials 与通配符冲突‌ allowCredentials(true) 时不可用 allowedOrigins("*") ‌8 指定具体域名:.allowedOrigins("domain.com")
‌多路径规则冲突‌ 不同路径的 CORS 配置相互覆盖 使用 CorsFilter 实现动态路由级配置 ‌37

四、选型建议(结合官方文档)
  • 简单项目:优先使用 CorsInterceptor(通过 addCorsMappings 配置),减少代码侵入性
  • 复杂项目:选择 CorsFilter,尤其在存在自定义拦截器、动态域名等场景
  • 混合方案:对特定路径使用 @CrossOrigin 注解,全局规则通过 CorsFilter 实现

原创声明:本文结论基于 Spring 6.1.9 源码及官方文档验证,转载需授权。

相关推荐
华仔啊27 分钟前
工作5年没碰过分布式锁,是我太菜还是公司太稳?网友:太真实了!
java·后端
卿·静42 分钟前
Node.js对接即梦AI实现“千军万马”视频
前端·javascript·人工智能·后端·node.js
SamDeepThinking1 小时前
在 Cursor IDE 中配置 SQLTools 连接 MySQL 数据库指南(Windows 11)
后端·ai编程·cursor
武子康1 小时前
大数据-92 Spark 深入解析 Spark Standalone 模式:组件构成、提交流程与性能优化
大数据·后端·spark
青梅主码2 小时前
麦肯锡最新发布报告《想打破生产力天花板吗?重新思考完成工作的方式》:与其一味调整组织结构,不如从根本上简化工作流程,释放更大价值
后端
Python私教2 小时前
源滚滚Rust全栈班v1.02 无符号整数详解
开发语言·后端·rust
绝无仅有2 小时前
面试总结之Nginx 经验常见问题汇总第二篇
后端·面试·github
这里有鱼汤2 小时前
分享7种常见的量化交易策略
后端
绝无仅有2 小时前
面试实战总结之Nginx配置经验第一篇
后端·面试·github
shark_chili3 小时前
CPU性能优化三剑客:分支预测、并行运算与超线程技术深度解析
后端