vue/react调用thinkphp接口出现cors错误,需按路由级、中间件或入口文件三方式配置跨域:路由级用allowcrossdomain()并注意参数规则;中间件须前置且拦截options;入口文件兜底时origin不可为*。

前端 Vue 或 React 项目调用 ThinkPHP 6/8 后端 API 时,页面空白、控制台报 CORS 错误、OPTIONS 请求卡在 pending 状态——这不是前端写错了,而是后端跨域响应头没在正确时机、以正确方式发出。官方不认 config/cors.php,中间件注册顺序错一位就失效,带 Cookie 的请求配了 * 就直接被浏览器丢弃。
路由级跨域:只开 API 接口,最省事也最安全
适合前后端分离项目,仅对 /api/ 开头的接口开放跨域,不影响后台管理、命令行等其他路由。
第一步:在 route/app.php 中定义路由时,把 ->allowCrossDomain() 写在链式调用末尾,不能漏括号,也不能写在闭包里:
Route::post('api/login', 'Api/Login@login')->allowCrossDomain();
第二步:需要前端携带 Cookie 或 Authorization 头时,必须传两个参数,且第一个参数不能是 *:
Route::get('api/user', 'Api/User@index')->allowCrossDomain(['https://admin.example.com', 'http://localhost:3000'], true);
【第二个参数为 true 时,第一个参数必须是明确域名数组,绝不能含 *】
第三步:确认该路由是 HTTP/HTTPS 类型——console、event、rpc 路由不会触发 allowCrossDomain(),写了也无效。
全局跨域中间件:全站统一管控,但必须拦住 OPTIONS
当你需要所有接口(包括非 /api/ 路径)都支持跨域,或需动态校验 Origin 时,必须用自定义中间件,且开头必须拦截 OPTIONS 请求。
方法一:启用 ThinkPHP 官方内置中间件(TP6.1+ / TP8)
编辑 app/middleware.php,在返回数组中加入:
\think\middleware\AllowCrossDomain::class,
【必须放在数组靠前位置,确保它比 Session、Auth 等中间件更早执行】
方法二:手写轻量中间件(兼容 TP6.0 及所有版本)
在 app/middleware/Cors.php 中写入:
if ($request->isOptions()) { return response('', 204); }
$response->header([
'Access-Control-Allow-Origin' => $origin ?? 'https://your-frontend.com',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Headers' => 'Authorization,Content-Type,X-Requested-With,X-Token',
'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS'
]);
注意:Access-Control-Allow-Headers 必须显式列出前端实际发送的字段,不能写 * —— 前端发 X-Token,这里就得写 X-Token,大小写严格匹配。
入口文件兜底方案:简单粗暴,适合调试或临时上线
当所有中间件方案都因部署环境(如 Nginx 拦截 OPTIONS、Swoole 配置异常)失效时,直接在 public/index.php 最顶部插入:
header('Access-Control-Allow-Origin: https://admin.example.com');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization,Content-Type,X-Requested-With,X-Token');
header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { exit; }
这一步操作起来很简单,直接把五条 header 和 exit 放进去就行。但要注意:Origin 不能写 *,否则带凭证的请求会被浏览器静默拒绝。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











