Apache配置CORS需三者齐备:启用mod_headers模块、完整设置响应头、确保OPTIONS请求返回200;缺一即导致预检失败。

Apache 配置 CORS 的核心不是“加几个头”,而是三件事必须同时到位:模块启用、响应头发全、OPTIONS 请求能正常返回 200。漏掉任何一环,前端都会卡在预检(preflight)阶段,报错看似是跨域失败,实际可能是模块没开或 OPTIONS 被拦截。
确认并启用 mod_headers 模块
这是所有配置的前提。Apache 默认不加载该模块,Header 指令会直接报错或静默失效。
- 检查是否已启用:apache2ctl -M | grep headers(Debian/Ubuntu)或 httpd -M | grep headers(RHEL/CentOS);无输出即未启用
- 启用方式:sudo a2enmod headers(Linux 发行版),或编辑 httpd.conf 取消注释 LoadModule headers_module modules/mod_headers.so(Windows 下的 phpEnv 同理)
- 改完必须重启服务:sudo systemctl restart apache2 或 sudo apachectl restart
在合适位置写入 CORS 响应头
推荐优先使用
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 基础配置示例(开发环境可用):
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "http://localhost:3000"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE"
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Max-Age "86400"
Header append Vary Origin
</IfModule> - 生产环境严禁用 * 配合 Access-Control-Allow-Credentials true,否则浏览器直接拒绝;必须指定确切域名,如 "https://app.yourcompany.com"
- 如果 API 由 Apache 反向代理到后端(如 PHP-FPM 或 Node.js),这些头仍可统一加在 Apache 层,无需改动业务代码
必须显式处理 OPTIONS 预检请求
只要前端发了 Authorization、Content-Type: application/json 或任意自定义 Header,浏览器就会先发 OPTIONS 请求。Apache 默认不响应它,请求就一直 pending。
- 最稳妥方案:启用 mod_rewrite 并添加规则:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L] - 轻量替代:在对应
或 块内加 Require all granted,确保 OPTIONS 不被访问控制拦截 - 注意:.htaccess 中的配置受 AllowOverride FileInfo 控制,若服务器禁用该指令,则 .htaccess 内的 Header 指令完全不生效
让预检结果真正被浏览器缓存
Access-Control-Max-Age 只有在 OPTIONS 响应中稳定存在,浏览器才会缓存预检结果。普通响应里的这个头无效。
- 不能只写在
里,必须绑定到 OPTIONS 方法本身:
<Limit OPTIONS>
Header always set Access-Control-Allow-Origin "https://app.yourcompany.com"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type, Authorization"
Header always set Access-Control-Max-Age "86400"
</Limit> - 如果用了 Access-Control-Allow-Credentials true,Access-Control-Allow-Origin 必须是具体域名,不能是 *,否则浏览器拒绝缓存
- 前端实际发送的自定义 Header(如 X-App-Version 或 RIDER-APPKEY)必须完整列在 Access-Control-Allow-Headers 中,少一个,预检就 403

















