XAMPP 默认不支持跨域,必须启用 mod_headers 模块、正确配置响应头、放行 OPTIONS 方法三者缺一不可;仅改端口只触发 CORS 机制,无法解决响应头缺失问题。

XAMPP 默认不支持跨域,光改端口没用;必须启用 mod_headers 模块 + 正确配置响应头 + 放行 OPTIONS 方法,三者缺一不可。
为什么只改 Apache 端口(如 8080、8081)解决不了 CORS?
浏览器判断跨域依据是「协议 + 域名 + 端口」三者组合,改端口确实会让前端和后端变成不同源——但这只是触发 CORS 的条件,不是解决方案。真正卡住请求的,是服务器没返回合法的 Access-Control-Allow-Origin 等响应头,而这些头必须靠 mod_headers 模块才能设置。
常见错误现象:
前端发请求到 http://localhost:8080/api,控制台报 No 'Access-Control-Allow-Origin' header,但 Network 面板里响应状态是 200 ——说明请求通了,只是头没发出来。
- XAMPP 的
httpd.conf默认注释掉了LoadModule headers_module modules/mod_headers.so - 不取消注释并重启 Apache,所有
Header set配置都无效 - 即使你开了多个端口(比如 80、8080、8081),只要没加载这个模块,全端口都一样跨不过去
如何在多端口虚拟主机中分别配置 CORS 头
不能靠 .htaccess:XAMPP 默认禁用 Header 指令覆盖,直接放 .htaccess 会 500 错误。必须在 httpd-vhosts.conf 里为每个端口对应的 <virtualhost></virtualhost> 或 <directory></directory> 块里写。
例如,你用 8080 和 8081 两个端口跑不同项目:
XAMPP 8.0.30 是一款免费、开源的跨平台 Web 服务器集成包,专为快速搭建本地 PHP 开发环境而设计。该版本核心组件包括:Apache 2.4.56、MySQL 8.0.33、PHP 8.0.30、phpMyAdmin 5.2.1 等。它支持 Windows、Linux 和 macOS 系统,可让开发者在个人电脑上轻松模拟服务器环境,无需复杂配置即可运行 WordPress、Thin
<VirtualHost *:8080>
DocumentRoot "X:/xampp/htdocs/project-a"
<Directory "X:/xampp/htdocs/project-a">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
Header set Access-Control-Allow-Origin "http://localhost:3000"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE"
Header set Access-Control-Allow-Headers "Content-Type, X-Requested-With, Authorization"
Header set Access-Control-Allow-Credentials "true"
</Directory>
</VirtualHost>
<VirtualHost *:8081>
DocumentRoot "X:/xampp/htdocs/project-b"
<Directory "X:/xampp/htdocs/project-b">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
Header set Access-Control-Allow-Origin "http://localhost:5173"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type"
</Directory>
</VirtualHost>
- 生产环境必须写明确域名,
"*"不适用于带凭证(credentials: true)的请求 - 两个端口可以配不同白名单,互不影响
- 如果某个项目不需要凭证,
Access-Control-Allow-Credentials这行可删
为什么 OPTIONS 预检请求总返回 405 Method Not Allowed?
这不是 CORS 配置错了,是 Apache 默认拒绝 OPTIONS 方法。哪怕你加了所有 Header,只要没显式允许该方法,预检就失败。
在对应 <directory></directory> 或 <virtualhost></virtualhost> 块里加这一行即可:
Require method GET POST HEAD OPTIONS
- 不要只写
Require all granted——它控制的是访问权限,不等于放开 HTTP 方法 - 如果你用了
mod_rewrite,还要检查有没有RewriteRule把OPTIONS重定向或 404 掉 - Chrome 控制台看到
405时,点开 Network → 选中那个OPTIONS请求 → 查看 Response Headers,如果空空如也,基本就是这个原因
容易被忽略的缓存与调试陷阱
改完配置重启 Apache 后,浏览器可能还在用旧响应头——尤其当你之前测试过带 credentials 的请求,浏览器会缓存预检结果长达 24 小时。
- 开发阶段清空浏览器缓存,或用无痕窗口测试
- 临时禁用 Chrome 插件(特别是某些“跨域调试”类插件,它们会伪造响应头干扰判断)
- 用
curl -I http://localhost:8080/api直接看原始响应头,绕过浏览器层干扰 - 如果用了反向代理(比如 Nginx 套在 Apache 前面),CORS 头得在代理层加,Apache 配置无效
最常漏掉的其实是第一件事:改完 httpd.conf 里的 mod_headers 注释,却忘记重启 Apache。所有后续操作都建立在这个前提上,它不生效,后面全是徒劳。

















