You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:31:33