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

Angular跨域请求缺失CORS响应头问题排查与解决咨询

Angular跨域GET请求中CORS响应头缺失问题排查与解决

问题背景

架构链路:

browser --- nginx --- apache --- tomcat9

现象细节:

  • 浏览器直接访问目标页面时,Firefox网络调试器可见响应包含CORS相关头:
Access-Control-Allow-Headers    Content-Type
Access-Control-Allow-Origin *
  • 通过Angular应用访问同一页面时,上述CORS响应头完全缺失。无论请求来自localhost、其他主机还是同一主机,该问题均存在(同一主机访问时请求可正常执行,但响应头仍不显示)。
  • 诉求:不想在Nginx/Apache等基础设施层面添加CORS头,希望在Tomcat应用层解决问题。

现有配置代码

Tomcat的CORS过滤器实现

@WebFilter()
public class ResponseFilter implements Filter {

  private static final String CONTENT_TYPE = "Content-Type";
  private static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers";
  private static final String VALUE = "*";
  private static final String CORS_HEADER = "Access-Control-Allow-Origin";

  @Override
  public void doFilter(final ServletRequest request, final ServletResponse response,
      final FilterChain chain) throws IOException, ServletException {
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    httpServletResponse.setHeader(
        CORS_HEADER, VALUE);
    httpServletResponse.setHeader(
        ACCESS_CONTROL_ALLOW_HEADERS, CONTENT_TYPE);
    chain.doFilter(request, response);
  }

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

  @Override
  public void destroy() {
  }
}

Apache代理配置片段

ProxyPass / http://localhost:8080/
<LocationMatch /.*>
#    DirectoryIndex off
    RewriteEngine Off
    AuthType openid-connect
    AllowOverride None
    Require valid-user
</LocationMatch> 

Nginx代理配置片段

server {
listen 443 ssl;
server_tokens off;
      server_name  <server name>;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_certificate <filename>; # managed by Certbot
    ssl_certificate_key <filename>; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

  add_header Strict-Transport-Security max-age=63072000;

location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://<ip address>:<port>;
    }
}

原因分析

  1. 过滤器匹配范围不足:Tomcat过滤器使用@WebFilter()未指定urlPatterns,默认匹配范围可能不覆盖Angular发起请求的路径,导致过滤器未执行,CORS头未被设置。而浏览器直接访问的路径刚好在默认匹配范围内。
  2. 未处理OPTIONS预检请求:Angular的HttpClient可能因请求头或请求方式触发CORS预检OPTIONS请求,当前过滤器未针对OPTIONS请求做特殊处理,导致预检响应无CORS头,浏览器后续会隐藏实际GET请求的响应头。
  3. 代理服务器头传递问题:Apache的认证拦截逻辑可能在Tomcat返回响应前提前生成响应,覆盖或丢失了Tomcat设置的CORS头;Nginx默认虽会传递后端响应头,但如果存在头过滤配置也会导致CORS头丢失。

解决方案

1. 修正Tomcat过滤器的匹配范围

给@WebFilter添加明确的路径匹配规则,确保覆盖所有Angular请求路径:

@WebFilter(urlPatterns = "/*") // 匹配所有请求路径
public class ResponseFilter implements Filter {
    // 原有代码逻辑不变
}

2. 新增OPTIONS预检请求处理

在过滤器中直接响应OPTIONS请求,避免后续链处理,同时补全必要的CORS头:

@Override
public void doFilter(final ServletRequest request, final ServletResponse response,
    final FilterChain chain) throws IOException, ServletException {
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  HttpServletRequest httpServletRequest = (HttpServletRequest) request;

  // 设置基础CORS头
  httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
  httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
  httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
  httpServletResponse.setHeader("Access-Control-Max-Age", "3600");

  // 处理OPTIONS预检请求,直接返回200状态码
  if ("OPTIONS".equalsIgnoreCase(httpServletRequest.getMethod())) {
      httpServletResponse.setStatus(HttpServletResponse.SC_OK);
      return;
  }

  chain.doFilter(request, response);
}

3. 确保代理服务器传递响应头(可选,若必须在应用层解决可跳过)

如果是Apache/Nginx代理导致头丢失,可添加强制传递配置:

  • Apache在LocationMatch块中添加:
Header always pass Access-Control-Allow-Origin
Header always pass Access-Control-Allow-Headers
  • Nginx在location块中添加:
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Headers;

4. 检查Angular请求头

如果Angular请求添加了自定义头(如Authorization),需要在过滤器的Access-Control-Allow-Headers中包含这些头,避免因头不匹配导致CORS失败。

内容的提问来源于stack exchange,提问作者Árpád Magosányi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:02:43