Spring MVC自定义拦截器致@CrossOrigin失效的跨域问题求助
解决自定义拦截器导致@CrossOrigin失效的问题
这个问题我之前也碰到过,其实核心原因就是自定义拦截器的执行顺序比Spring内置的跨域处理拦截器更早,导致OPTIONS预检请求还没被@CrossOrigin对应的逻辑处理,就被自定义拦截器拦截或者跳过了跨域头的设置,最终注解失效。下面给你几个可行的解决方案:
方案1:调整自定义拦截器的执行顺序
Spring内置的Cors拦截器优先级是Ordered.HIGHEST_PRECEDENCE + 10(数值为-2147483638),我们只需要让自定义拦截器的优先级比它低,就能保证跨域逻辑先执行。
在你的MVC配置类里,注册拦截器时指定order参数,把自定义拦截器的顺序设为更低优先级的值,比如Ordered.LOWEST_PRECEDENCE:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private CustomInterceptor customInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customInterceptor) .addPathPatterns("/**") .order(Ordered.LOWEST_PRECEDENCE); // 让自定义拦截器最后执行 } }
这样Spring会先处理跨域请求,设置好响应头后,再执行你的自定义拦截逻辑,@CrossOrigin就能正常生效了。
方案2:在自定义拦截器中手动处理跨域预检请求
如果不想调整顺序,也可以在自定义拦截器的preHandle方法里,先放行OPTIONS预检请求并手动设置跨域响应头,避免它被拦截:
public class CustomInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 先处理OPTIONS预检请求,直接放行并设置跨域头 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); response.setHeader("Access-Control-Max-Age", "3600"); response.setStatus(HttpServletResponse.SC_OK); return true; } // 这里写你的自定义拦截逻辑,比如token校验、日志记录等 return true; } }
注意这里的响应头要和你@CrossOrigin里的配置保持一致,比如maxAge=3600就对应Access-Control-Max-Age的值。
方案3:改用全局跨域配置替代@CrossOrigin
如果项目中大部分接口都需要跨域,不如直接配置全局Cors规则,这样既不用给每个Controller加注解,也能完美兼容自定义拦截器:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private CustomInterceptor customInterceptor; // 全局跨域配置 @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .maxAge(3600); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customInterceptor) .addPathPatterns("/**"); // 全局Cors的拦截器优先级默认更高,不用额外调整顺序 } }
配置完后,就可以去掉Controller上的@CrossOrigin注解了,所有接口都会自动应用跨域规则。
几个注意点
- 如果用方案1,一定要确保自定义拦截器的
order数值大于内置Cors拦截器的-2147483638,比如设为0、正数或者直接用Ordered.LOWEST_PRECEDENCE。 - 如果自定义拦截器有请求校验逻辑(比如token验证),一定要跳过OPTIONS请求,不然预检请求会被拦截导致跨域失败。
- 尽量不要同时混用
@CrossOrigin和全局Cors配置,避免出现规则冲突。
内容的提问来源于stack exchange,提问作者Jimfang Loo
相关产品推荐
相关产品推荐

