<p>ThinkPHP 6.0.16 必须手写 CorsMiddleware 并前置注册,拦截 OPTIONS 请求返回 204,通过 $response->header() 设置 Access-Control-Allow-Origin(非 * 时才支持 credentials)、Methods 和 Headers,确保不被后续逻辑覆盖。</p>

ThinkPHP 6.0.16 中没有内置 CORS 中间件,必须手写一个,并确保它在路由匹配前执行、响应头通过 Response 对象 设置,且不被后续逻辑覆盖。否则即使写了中间件,浏览器依然报错“No 'Access-Control-Allow-Origin' header”。
中间件必须拦截 OPTIONS 预检请求
浏览器只要带 Authorization、X-Requested-With 或自定义 Header,就会先发 OPTIONS 请求。TP6 默认会拦截 OPTIONS 方法(尤其开启 method_filter 时),导致 405 错误或空白响应。
- 在
handle()开头加判断:if ($request->isOptions()) { return response('', 204); } - 同时确认
config/app.php中'method_filter' => false,或把'OPTIONS'加入白名单数组 - 调试时用
curl -X OPTIONS -I http://your-api.com/api/user查看真实响应头,别只信浏览器 Network 面板
响应头必须用 $response->header() 设置
不能用原生 header() 函数或 echo,TP6 的响应是封装对象,手动输出会被覆盖。
- 必须调用
$next($request)获取$response实例,再链式设置头 - 关键头至少包含:
Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers - 若前端启用了
withCredentials: true(如传 cookie),则Access-Control-Allow-Origin不能为*,必须写具体域名,例如https://admin.example.com
中间件注册位置决定是否生效
中间件必须在请求生命周期最外层执行,否则可能被路由、验证、异常处理等中间件覆盖响应头。
立即学习“PHP免费学习笔记(深入)”;
- 推荐在
app/middleware.php全局中间件数组中注册,且放在首位 - 也可在
route/app.php中对某组路由显式挂载:Route::group('api', function () {...})->middleware(\app\middleware\CorsMiddleware::class) - 避免在闭包路由里漏掉
->middleware()调用,或把它写在->allowCrossDomain()后面——后者优先级更高,会覆盖中间件头
带凭据时需前后端同步配置
只后端设 Access-Control-Allow-Credentials: true 不够,前端 fetch 或 axios 也必须开启凭据支持。
- 后端:响应头含
Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin是具体域名(不可为*) - 前端:fetch 需加
credentials: 'include';axios 需设withCredentials: true - 若使用 Nginx 反向代理,还需透传 Origin 头:
proxy_set_header Origin $http_origin;,否则 Swoole 或 PHP 层收不到原始 Origin



















