Tomcat配置CORS后仍遇跨域拦截,OPTIONS请求返回403求助
问题
跨域调用Tomcat后端服务时触发CORS错误,React前端收到如下提示:
Access to fetch at 'https://tomcat:8443/post/service ' from origin 'https://domainReact:8443/react' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
后端Tomcat 9配置(conf/web.xml)
<filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.allowed.origins</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.support.credentials</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.request.decorate</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowed.methods</param-name> <param-value>GET,POST,DELETE,OPTIONS,PUT</param-value> </init-param> <init-param> <param-name>cors.allowed.headers</param-name> <param-value>Content-Type,X-Requested-With,Access-Control-Request-Method,Access-Control-Request-Headers,accept,Origin,Access-Control-Allows-Origin,alias,Authorization,customerId</param-value> </init-param> <init-param> <param-name>cors.exposed.headers</param-name> <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials,Access-Control-Request-Headers</param-value> </init-param> <init-param> <param-name>cors.preflight.maxage</param-name> <param-value>1728000</param-value> </init-param> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>CSRF</filter-name> <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class> <init-param> <param-name>entryPoints</param-name> <param-value>/html,/html/</param-value> </init-param> </filter> <filter-mapping> <filter-name>httpHeaderSecurity</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping> <filter-mapping> <filter-name>CSRF</filter-name> <servlet-name>servlet</servlet-name> </filter-mapping>
网络请求详情
请求信息
General: Request URL: https://tomcat:8443/post/service Request Method: OPTIONS Status Code: 403 Remote Address: 172.16.0.233:8443 Referrer Policy: strict-origin-when-cross-origin Request Headers: :authority: https://tomcat:8443 :method: OPTIONS :path: /post/service :scheme: https accept: */* accept-encoding: gzip, deflate, br access-control-request-headers: alias,authorization,content-type,customerid access-control-request-method: POST access-control-request-private-network: true origin: https://domainReact:8443/react referer: https://domainReact:8443/react/ sec-fetch-dest: empty sec-fetch-mode: cors sec-fetch-site: same-site
响应信息
Response Headers: cache-control: private content-length: 683 content-type: text/html;charset=utf-8
补充说明
- 使用
alias、customerId两个自定义请求头,API通过JAX-RS暴露,未配置额外CORS过滤器 - 移除Tomcat的
CorsFilter后错误依旧 - Java调用服务正常,仅React/JavaScript调用出现问题
- 已将自定义头添加到Tomcat过滤器配置,但响应中看不到CORS相关头信息
解决分析与方案
核心问题:CSRF过滤器拦截了OPTIONS预检请求
从403状态码和配置顺序来看,CsrfPreventionFilter是导致预检请求失败的关键:
- 跨域预检的OPTIONS请求不在CSRF过滤器的
entryPoints列表中,被判定为非法请求直接返回403 - 由于过滤器映射顺序由配置顺序决定,CSRF过滤器在CorsFilter之前执行,OPTIONS请求还没到CorsFilter就被拦截
修复步骤
更新CSRF过滤器的
entryPoints参数,将OPTIONS请求或目标接口路径加入允许列表:<filter> <filter-name>CSRF</filter-name> <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class> <init-param> <param-name>entryPoints</param-name> <!-- 方式1:添加目标接口路径 --> <param-value>/html,/html/,/post/service</param-value> <!-- 方式2:直接允许所有OPTIONS请求 --> <!-- <param-value>/html,/html/,OPTIONS</param-value> --> </init-param> </filter>调整过滤器执行顺序,确保
CorsFilter在CsrfPreventionFilter之前处理请求:
在web.xml中把CorsFilter的配置和映射代码段,移到CSRF过滤器的配置前面,让预检请求先被CorsFilter处理并返回合法响应。统一自定义请求头的大小写:
配置中cors.allowed.headers是customerId,但请求头里是全小写的customerid,虽然HTTP头不区分大小写,但部分框架可能存在严格匹配问题,建议统一为小写或保持一致。验证CORS过滤器生效状态:
确认Tomcat 9自带的CorsFilter依赖正常,且过滤器的url-pattern(当前为/*)覆盖了所有需要跨域的接口路径。
额外验证
- 测试前清空浏览器缓存,避免旧的错误响应干扰
- 查看Tomcat日志,确认OPTIONS请求是否被CSRF过滤器拦截的记录
内容的提问来源于stack exchange,提问作者David D

