关键是要在options响应中显式设置access-control-max-age,需启用mod_headers模块,用配合header always set绑定该头,并确保origin与credentials兼容,否则浏览器无法缓存预检。

要在 Apache 中让跨域预检请求(OPTIONS)被浏览器缓存,关键不是给普通响应加 Access-Control-Max-Age,而是确保 OPTIONS 请求的响应里**明确、稳定、无干扰地返回这个头**。否则浏览器每次都会重发预检,无法复用。
必须启用并确认 mod_headers 模块
Apache 默认不启用 mod_headers,没它就无法设置任何 CORS 响应头。
- 检查是否已加载:
apache2ctl -M | grep headers(Debian/Ubuntu)或httpd -M | grep headers(RHEL/CentOS) - 若无输出,运行
sudo a2enmod headers或在httpd.conf中取消注释:LoadModule headers_module modules/mod_headers.so -
改完必须重启服务:
sudo systemctl restart apache2或sudo systemctl restart httpd
只对 OPTIONS 方法显式设置 Access-Control-Max-Age
Access-Control-Max-Age 只在 OPTIONS 响应中生效,且 Apache 不会自动把它加到预检响应里——你得手动绑定到 OPTIONS 方法上。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 不能写在
<directory></directory>或<location></location>块里用Header set,那样对 OPTIONS 常失效 - 必须用
<limit options></limit>+Header always set组合,确保头被强制注入,哪怕响应由 proxy 或静态处理模块生成 - 示例配置(放在 VirtualHost 或主配置中):
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,PATCH,HEAD,OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type,X-Requested-With,Authorization"
Header always set Access-Control-Max-Age "86400"
Header always set Access-Control-Allow-Credentials "true"
注意 Origin 和 Credentials 的兼容性
如果需要支持凭据(如 Cookie、Authorization),Access-Control-Allow-Origin 就不能设为 *,否则浏览器直接拒绝缓存预检结果。
- 生产环境应指定具体域名,例如:
Header always set Access-Control-Allow-Origin "https://your-app.com" - 此时
Access-Control-Allow-Credentials可设为true,且预检缓存仍可生效 - 若 Origin 不匹配或被中间代理(如 CDN、Nginx 反向代理)清洗掉该头,缓存也会失效
验证是否真正生效
光看配置不够,要实测浏览器行为:
- 打开开发者工具 → Network → 发起一个触发预检的请求(比如带
Content-Type: application/json的 POST) - 找到对应的 OPTIONS 请求,点开 Response Headers,确认存在
Access-Control-Max-Age: 86400 - 刷新页面再发同样请求,若不再出现新的 OPTIONS 条目,说明缓存已起作用
- 若仍有重复 OPTIONS,优先排查:代理是否透传头、Origin 是否动态变化、是否用了通配符却开了凭据










