如何设置ThinkPHP中的CORS跨域请求?
- 内容介绍
- 文章标签
- 相关推荐
本文共计990个文字,预计阅读时间需要4分钟。
ThinkPHP 6 简介:
路由级 allowCrossDomain() 怎么用才有效
这是 ThinkPHP 6 官方推荐、最轻量也最可控的方式,只对指定 API 路由生效,不污染其他逻辑。
- 必须在
route/app.php中定义 HTTP/HTTPS 路由后链式调用:->allowCrossDomain(),写在闭包里或漏掉链式调用都会失效 - 不传参默认设
Access-Control-Allow-Origin: *;要指定来源,传数组:->allowCrossDomain(['https://admin.example.com', 'http://localhost:3000']) - 前端带 Cookie 或
Authorization头时,第二个参数必须为true:->allowCrossDomain(['https://example.com'], true),否则浏览器静默拦截 - 该方法对
console或event类路由无效,别试图用它处理命令行任务
CorsMiddleware 中 OPTIONS 预检怎么不报 405
全局中间件里只加响应头是错的,90% 的跨域失败都卡在 OPTIONS 请求没被正确响应。
- 在
handle()方法开头加判断:if ($request->isOptions()) { return response('', 204); },必须短路返回,不能走$next($request) -
204状态码比200更规范,避免某些代理或 CDN 对空响应体做额外处理 - 设置响应头时,
Access-Control-Allow-Methods必须包含实际用到的动词(如PUT、DELETE),且一定含OPTIONS;Access-Control-Allow-Headers要覆盖前端发的全部自定义头,比如Authorization、X-Requested-With、Content-Type - 中间件注册位置很重要:必须放在
app/middleware.php全局中间件数组的**首位**,确保它最先执行、最后结束,不被后续中间件覆盖头信息
Access-Control-Allow-Origin 写 * 还是具体域名
取决于前端是否需要传 Cookie、Authorization 或其他凭证。二者互斥,选错就彻底失败。
立即学习“PHP免费学习笔记(深入)”;
- 如果前端
fetch配了credentials: 'include'或 jQuery 用了xhrFields: { withCredentials: true },后端就必须设Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin**不能是***,必须是精确匹配的协议+域名,比如https://a.com - 生产环境强烈建议动态校验
$request->header('Origin')是否在白名单内,再回写对应 Origin 值,而不是硬编码一个域名——否则换测试域名就得改代码 - ThinkPHP 5.1 在控制器里用
header()易触发headers already sent错误,应改用response($data)->header(...),且必须在return前调用,不能穿插echo或dump()
Nginx 反向代理下 Origin 头丢失怎么办
当 Nginx → Swoole 或 Nginx → PHP-FPM 多层代理时,原始 Origin 头常被吞掉,导致后端读不到,白名单校验永远失败。
- 在 Nginx 的
location块里显式透传:proxy_set_header Origin $http_origin;,不是$sent_http_origin,也不是漏写 - 如果用了多级代理(比如 Cloudflare → Nginx → Swoole),还需确认上一级是否剥离了
Origin,必要时用add_header回填,但注意和 PHP 设置的头冲突 - Swoole 模式下,
$_SERVER['HTTP_ORIGIN']可能为空,优先用$request->header('Origin')获取,更稳定
真正容易被忽略的是预检请求的生命周期控制——它不进控制器、不走业务逻辑,只靠中间件拦截并干净返回;还有就是 Origin 校验必须在响应头写入前完成,晚一步就只能返回 * 或报错。
本文共计990个文字,预计阅读时间需要4分钟。
ThinkPHP 6 简介:
路由级 allowCrossDomain() 怎么用才有效
这是 ThinkPHP 6 官方推荐、最轻量也最可控的方式,只对指定 API 路由生效,不污染其他逻辑。
- 必须在
route/app.php中定义 HTTP/HTTPS 路由后链式调用:->allowCrossDomain(),写在闭包里或漏掉链式调用都会失效 - 不传参默认设
Access-Control-Allow-Origin: *;要指定来源,传数组:->allowCrossDomain(['https://admin.example.com', 'http://localhost:3000']) - 前端带 Cookie 或
Authorization头时,第二个参数必须为true:->allowCrossDomain(['https://example.com'], true),否则浏览器静默拦截 - 该方法对
console或event类路由无效,别试图用它处理命令行任务
CorsMiddleware 中 OPTIONS 预检怎么不报 405
全局中间件里只加响应头是错的,90% 的跨域失败都卡在 OPTIONS 请求没被正确响应。
- 在
handle()方法开头加判断:if ($request->isOptions()) { return response('', 204); },必须短路返回,不能走$next($request) -
204状态码比200更规范,避免某些代理或 CDN 对空响应体做额外处理 - 设置响应头时,
Access-Control-Allow-Methods必须包含实际用到的动词(如PUT、DELETE),且一定含OPTIONS;Access-Control-Allow-Headers要覆盖前端发的全部自定义头,比如Authorization、X-Requested-With、Content-Type - 中间件注册位置很重要:必须放在
app/middleware.php全局中间件数组的**首位**,确保它最先执行、最后结束,不被后续中间件覆盖头信息
Access-Control-Allow-Origin 写 * 还是具体域名
取决于前端是否需要传 Cookie、Authorization 或其他凭证。二者互斥,选错就彻底失败。
立即学习“PHP免费学习笔记(深入)”;
- 如果前端
fetch配了credentials: 'include'或 jQuery 用了xhrFields: { withCredentials: true },后端就必须设Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin**不能是***,必须是精确匹配的协议+域名,比如https://a.com - 生产环境强烈建议动态校验
$request->header('Origin')是否在白名单内,再回写对应 Origin 值,而不是硬编码一个域名——否则换测试域名就得改代码 - ThinkPHP 5.1 在控制器里用
header()易触发headers already sent错误,应改用response($data)->header(...),且必须在return前调用,不能穿插echo或dump()
Nginx 反向代理下 Origin 头丢失怎么办
当 Nginx → Swoole 或 Nginx → PHP-FPM 多层代理时,原始 Origin 头常被吞掉,导致后端读不到,白名单校验永远失败。
- 在 Nginx 的
location块里显式透传:proxy_set_header Origin $http_origin;,不是$sent_http_origin,也不是漏写 - 如果用了多级代理(比如 Cloudflare → Nginx → Swoole),还需确认上一级是否剥离了
Origin,必要时用add_header回填,但注意和 PHP 设置的头冲突 - Swoole 模式下,
$_SERVER['HTTP_ORIGIN']可能为空,优先用$request->header('Origin')获取,更稳定
真正容易被忽略的是预检请求的生命周期控制——它不进控制器、不走业务逻辑,只靠中间件拦截并干净返回;还有就是 Origin 校验必须在响应头写入前完成,晚一步就只能返回 * 或报错。

