thinkphp 6 跨域首选路由级 ->allowcrossdomain(),轻量安全、仅作用于指定api路由;全局需自定义中间件并显式处理options预检(返回204),否则报405或静默失败;config/cors.php非官方配置,无效。

直接给结论:ThinkPHP 6 跨域问题,allowCrossDomain() 路由级配置最省事、最安全;全局统一处理必须用自定义中间件,且 OPTIONS 预检请求不拦截就会报 405 或静默失败。
路由级跨域:只对 API 路由生效,推荐首选
这个方法本质是给某条路由绑定一个轻量 CORS 中间件,不污染全局逻辑,适合前后端分离项目中仅开放 /api/ 类路径的场景。
-
->allowCrossDomain()必须写在路由定义链的末尾,比如Route::get('api/user', 'Api/User@index')->allowCrossDomain(),写在闭包里或漏掉括号都会失效 - 不传参默认设
Access-Control-Allow-Origin: *;要限制来源,传数组:->allowCrossDomain(['https://admin.example.com', 'http://localhost:3000']) - 前端带 Cookie 或 Authorization 头时,第二个参数必须为
true:->allowCrossDomain(['https://example.com'], true),否则浏览器直接拒绝 - 它只对 HTTP/HTTPS 路由起作用,
console或event路由无效,别指望它管命令行任务
全局 CORS 中间件:必须显式响应 OPTIONS 请求
全局中间件不是“加几个 header()”就完事。浏览器发预检请求(OPTIONS)时,如果后端没短路处理,框架会继续往下走——可能走到控制器抛出 404,或者返回 500,结果就是前端卡死、控制台只显示“CORS error”,连具体错误都看不到。
- 先执行
php think make:middleware CorsMiddleware创建中间件 - 在
handle()开头加判断:if ($request->isOptions()) { return response('', 204); },状态码必须是204或200,不能是201或404 - 在
return $next($request)之前设置响应头,例如:$response->header('Access-Control-Allow-Origin', 'https://your-frontend.com') - 若需支持
Content-Type: application/json或Authorization,Access-Control-Allow-Headers必须显式包含Content-Type和Authorization - 把中间件类完整命名空间加到
app/middleware.php的数组首位,确保它最先执行、最后结束
别碰 config/cors.php —— ThinkPHP 官方根本不认这个文件
很多教程抄 Laravel 的写法,在 ThinkPHP 里新建 config/cors.php 并试图通过 config('cors') 读取,结果跑起来直接报 Class 'think\middleware\Cors' not found。这不是你代码写错了,是框架压根没这个机制。
- ThinkPHP 6 没有内置
Cors中间件类,也没有自动加载config/cors.php的逻辑 - 如果你真想配置化管理白名单,可以自己建
config/cors.php返回数组,然后在中间件里手动config('cors.origin')读取——但这属于自行扩展,不是开箱即用功能 - 更常见的坑是:中间件里写了
header('Access-Control-Allow-Origin: *')又同时设了Access-Control-Allow-Credentials: true,浏览器会直接忽略整个响应,因为*和credentials: true是互斥的
真正容易被忽略的是 Origin 动态校验:当需要支持凭证(如登录态 Cookie)时,Access-Control-Allow-Origin 不能写死,也不能用 *,得从 $request->header('Origin') 读出来,再比对白名单数组,匹配成功才回写该 Origin。这个逻辑一旦漏掉,前端就永远收不到响应体。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











