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

Jersey CORS过滤器已配置,React REST GET请求仍跨域报错

Jersey+Tomcat跨域CORS配置失效,React请求预检失败解决指南

问题梳理

  • 环境:RH 8.6 服务器,Tomcat部署Jersey Servlet后端,React前端实现REST交互
  • 核心问题:
    1. React发起GET/POST请求时触发access-control-allow-origin头不被允许跨域错误
    2. 配置CORS过滤器后,Postman测试响应头正常,但React请求仍失败
    3. 调试发现过滤器能接收GET请求,但请求无法到达Jersey资源类端点
    4. React请求添加mode: 'no-cors'能收到响应头,但正常请求报错,控制台提示跨域请求被阻止,原因是预检响应的Access-Control-Allow-Headers不包含指定请求头

核心原因

  1. OPTIONS预检请求未正确处理:React携带Content-Type、Accept等自定义头的请求会触发浏览器OPTIONS预检,若后端未响应该请求或未配置允许的头/方法,直接导致跨域失败
  2. 过滤器执行顺序错误:Jersey的Servlet可能在CORS过滤器之前拦截请求,导致过滤器注入的响应头未生效,请求无法到达资源类
  3. CORS配置不完整:未明确允许React使用的请求头,也未将OPTIONS方法加入允许列表

分步解决方案

1. 补全CORS过滤器配置(强制覆盖OPTIONS请求)

无论使用web.xml配置还是自定义Filter类,都需确保以下配置:

  • 直接响应OPTIONS预检请求,无需走业务逻辑
  • 明确列出React请求中携带的所有自定义头
  • 允许的方法包含GET、POST、OPTIONS

web.xml配置示例:

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>com.xxx.yourpackage.CorsFilter</filter-class>
    <init-param>
        <param-name>allowedOrigins</param-name>
        <param-value>https://your-react-domain.com</param-value> <!-- 生产环境禁用*,写具体域名 -->
    </init-param>
    <init-param>
        <param-name>allowedMethods</param-name>
        <param-value>GET,POST,OPTIONS</param-value>
    </init-param>
    <init-param>
        <param-name>allowedHeaders</param-name>
        <param-value>Content-Type,Accept</param-value> <!-- 对应React请求头 -->
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern> <!-- 覆盖所有Jersey接口路径 -->
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>OPTIONS</dispatcher>
</filter-mapping>

自定义Filter类示例:

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        // 生产环境替换为你的React域名
        response.setHeader("Access-Control-Allow-Origin", "https://your-react-domain.com");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        // 必须包含React请求的所有自定义头
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        // 直接响应OPTIONS预检请求
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }

        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override
    public void destroy() {}
}

2. 调整过滤器与Jersey的执行顺序

在web.xml中,将CORS过滤器的<filter-mapping>放在Jersey的<servlet-mapping>之前,确保CORS过滤器优先处理请求,避免Jersey提前拦截导致响应头未注入。

3. 修正React请求代码

移除mode: 'no-cors'配置(该模式会返回无法读取内容的不透明响应),保持请求头与后端允许的一致:

fetch('http://your-tomcat-url/api/your-resource', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
})
.then(res => res.json())
.then(data => console.log('Success:', data))
.catch(err => console.error('Request failed:', err));

4. 浏览器工具验证预检请求

打开浏览器开发者工具Network面板,查看OPTIONS请求的响应头:

  • 确认Access-Control-Allow-Origin值为你的React域名
  • 确认Access-Control-Allow-Headers包含Content-Type、Accept
  • 确认Access-Control-Allow-Methods包含OPTIONS、GET、POST

额外排查项

  • 检查Tomcat全局配置(conf/web.xml)是否存在默认CORS过滤器,避免与自定义过滤器冲突
  • 确认Jersey资源类的@Path路径正确,过滤器的url-pattern覆盖该路径
  • 若使用Spring Boot整合Jersey,需排查Spring的CORS配置是否与Jersey冲突

内容的提问来源于stack exchange,提问作者John kerich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 14:15:35