从漏洞扫描到修复:手把手教你用Tomcat过滤器解决CORS安全问题

张开发
2026/4/10 8:27:50 15 分钟阅读

分享文章

从漏洞扫描到修复:手把手教你用Tomcat过滤器解决CORS安全问题
从漏洞扫描到修复手把手教你用Tomcat过滤器解决CORS安全问题在Java Web开发中跨域资源共享CORS是一个无法回避的话题。最近接手的一个企业级项目就遇到了典型的CORS安全漏洞——安全扫描工具显示当任意Origin头被注入时系统仍然返回了敏感数据。这种配置不当的CORS策略就像给保险箱装了一把任何人都能打开的锁。1. CORS漏洞的本质与危害CORS机制本是为了解决浏览器同源策略带来的合法跨域访问需求但错误的配置会将其变成安全漏洞。常见的高危配置包括Access-Control-Allow-Origin: *允许所有域访问Access-Control-Allow-Origin: null允许null源访问缺失Vary: Origin头导致缓存污染我曾遇到过这样一个案例某金融系统因为配置了*通配符导致攻击者可以构造恶意网页窃取用户会话。通过Burp Suite抓包可以看到GET /api/account HTTP/1.1 Origin: https://evil.comHTTP/1.1 200 OK Access-Control-Allow-Origin: https://evil.com Access-Control-Allow-Credentials: true这种响应意味着evil.com可以读取到带凭证的敏感数据。正确的做法应该是错误配置安全配置原理* Credentials白名单域名带凭证时禁止使用*静态域名列表动态校验Origin防止子域名绕过缺失Vary头添加Vary: Origin避免缓存污染2. Tomcat过滤器深度配置指南对于Spring Boot项目虽然可以通过CrossOrigin注解处理但在微服务架构下更推荐使用Tomcat全局过滤器。以下是经过生产验证的配置方案首先在pom.xml中添加dependency groupIdcom.thetransactioncompany/groupId artifactIdcors-filter/artifactId version2.10/version /dependency然后在src/main/webapp/WEB-INF/web.xml中配置filter filter-nameCORS/filter-name filter-classcom.thetransactioncompany.cors.CORSFilter/filter-class init-param param-namecors.allowOrigin/param-name param-valuehttps://trusted.com,https://*.trusted.org/param-value /init-param init-param param-namecors.supportedMethods/param-name param-valueGET, POST, HEAD, OPTIONS/param-value /init-param init-param param-namecors.supportedHeaders/param-name param-valueContent-Type,X-Requested-With/param-value /init-param init-param param-namecors.exposedHeaders/param-name param-valueSet-Cookie/param-value /init-param init-param param-namecors.supportsCredentials/param-name param-valuetrue/param-value /init-param init-param param-namecors.maxAge/param-name param-value3600/param-value /init-param /filter关键参数说明cors.allowOrigin支持通配符子域名(*.domain.com)cors.supportsCredentials设置为true时需要明确指定域名cors.maxAge预检请求缓存时间(秒)实际部署时发现当使用通配符子域名时必须确保父域名也在白名单中否则浏览器会拒绝带凭证的请求。3. 与Nginx的协同作战方案在多层架构中Nginx和Tomcat需要协同处理CORS。推荐的分工原则是Nginx处理静态资源的CORSTomcat处理API动态请求的CORS避免重复设置响应头典型的Nginx配置示例map $http_origin $cors_origin { default ; ~^https://([a-z0-9-]\.)?trusted\.com$ $http_origin; ~^https://(.*\.)?trusted-org\.org$ $http_origin; } server { location /api/ { if ($cors_origin) { add_header Access-Control-Allow-Origin $cors_origin; add_header Vary Origin; } proxy_pass http://tomcat-cluster; } location /static/ { if ($cors_origin) { add_header Access-Control-Allow-Origin $cors_origin; add_header Access-Control-Expose-Headers Content-Length; } alias /data/static/; } }这种配置的优势在于使用map实现高效域名匹配动态设置Vary头避免缓存问题静态资源与API采用不同的CORS策略只在检测到合法Origin时才添加CORS头4. 实战中的疑难问题排查在灰度发布过程中我们遇到过几个典型问题案例1预检请求失败现象OPTIONS请求返回403错误。原因是Tomcat默认禁止OPTIONS方法。解决方案是在web.xml中添加security-constraint web-resource-collection web-resource-nameCORS/web-resource-name url-pattern/api/*/url-pattern http-methodOPTIONS/http-method /web-resource-collection auth-constraint / /security-constraint案例2带Cookie请求失败排查步骤确认浏览器端设置了withCredentials: true检查服务端Access-Control-Allow-Credentials: true验证Access-Control-Allow-Origin不是通配符确保响应头中没有重复的CORS设置案例3IE11兼容性问题IE对CORS的实现有特殊要求需要明确设置Access-Control-Allow-Headers不支持credentials与*同时使用对缓存处理较为严格对应的解决方案是在过滤器中添加init-param param-namecors.supportedHeaders/param-name param-valueContent-Type,Authorization,X-Requested-With/param-value /init-param5. 安全加固进阶技巧除了基础配置外我们还实施了以下安全措施Origin验证强化public boolean isValidOrigin(String origin) { // 验证域名是否在预置白名单 // 验证协议必须是HTTPS // 验证端口是否在允许范围内 // 防止DNS重绑定攻击 }敏感接口特殊处理filter-mapping filter-nameCORS/filter-name url-pattern/api/public/*/url-pattern /filter-mapping filter-mapping filter-nameSecureCORS/filter-name url-pattern/api/private/*/url-pattern /filter-mapping监控与告警# 监控异常Origin请求 grep -E Origin: (?!https://trusted) /var/log/nginx/access.log自动化测试方案def test_cors_policy(): test_cases [ {origin: https://evil.com, expect: 403}, {origin: https://trusted.com, expect: 200}, {origin: null, expect: 403} ] for case in test_cases: resp requests.get(api_url, headers{Origin: case[origin]}) assert resp.status_code case[expect]在实施这些措施后安全扫描报告显示CORS相关漏洞已全部修复。整个过程让我深刻体会到安全配置不是简单的功能开关而是需要根据业务场景进行深度定制的防护体系。

更多文章