ThinkPHP 6 的 CorsMiddleware 未生效主因是注册位置错误——必须置于路由中间件栈最外层,否则预检请求或响应头无法正确处理;同时需规避通配符与凭据冲突、Web服务器拦截等常见问题。

ThinkPHP 6 的 CorsMiddleware 为什么没生效
多数情况不是中间件没配,而是它被注册在了错误位置——CorsMiddleware 必须放在路由中间件栈的最外层,否则后续中间件(比如验证、权限)可能提前中断请求,导致响应头根本没机会写入。
常见错误现象:OPTIONS 预检请求返回 200 但没带 Access-Control-Allow-Origin;或实际接口返回 403/401,浏览器控制台报“CORS header ‘Access-Control-Allow-Origin’ missing”。
- 确认中间件注册位置:在
app/middleware.php中,把CorsMiddleware::class放在数组最前面 - 别把它塞进某个控制器的
middleware属性里——那是局部中间件,不处理预检 - 如果用了多应用模式,检查是否在对应应用的
middleware.php中配置,而非全局
手动设置响应头比开中间件更可控的场景
当需要动态控制跨域策略(比如只允许特定域名、带凭据时限制 Origin 不能为通配符),中间件的静态配置反而容易翻车。
使用场景:后台 API 同时服务多个前端域名(admin.example.com、app.example.com),且部分接口需携带 cookies。
立即学习“PHP免费学习笔记(深入)”;
- 在基础控制器的
initialize()方法中加逻辑,而不是依赖中间件自动注入 - 务必先判断
$_SERVER['REQUEST_METHOD'] === 'OPTIONS',是则直接exit或返回空响应,避免执行业务逻辑 - 设置头时注意顺序:
Access-Control-Allow-Origin和Access-Control-Allow-Credentials: true必须同时存在,且前者不能是* - 示例:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { $this->response->header([ 'Access-Control-Allow-Origin' => $allowedOrigin, 'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS', 'Access-Control-Allow-Headers' => 'Content-Type,Authorization,X-Requested-With', 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Max-Age' => '3600' ]); return response('', 204); }
Access-Control-Allow-Origin 通配符与凭据冲突的硬限制
这是浏览器强制规范,不是 ThinkPHP 的 bug。只要响应头里有 Access-Control-Allow-Credentials: true,Access-Control-Allow-Origin 就绝不能写成 *,否则浏览器直接拒绝响应。
容易踩的坑:开发时本地用 http://localhost:3000 测试没问题,上线后切到正式域名就跨域失败,因为中间件配置里还留着 '*' => true 这类宽松写法。
- 检测当前请求的
Origin头,白名单匹配后才写具体域名,例如:https://admin.example.com - 不要在生产环境用
$_SERVER['HTTP_ORIGIN']直接回写——可能被伪造,必须校验是否在可信域名列表内 - 如果不需要凭据(如无登录态的公开接口),可设
Access-Control-Allow-Credentials: false,此时Access-Control-Allow-Origin: '*'才合法
预检请求(OPTIONS)被 Nginx / Apache 拦截的排查点
ThinkPHP 根本收不到 OPTIONS 请求,说明 Web 服务器层已拦截或返回默认响应,中间件压根没运行。
典型现象:Chrome Network 面板看到 OPTIONS 返回 405 Method Not Allowed,或直接 404;curl 测试也复现不了问题。
- Nginx 配置里检查是否有
limit_except或if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|PATCH)$) { return 405; }类规则 - Apache 需确认
mod_rewrite开启,且.htaccess没把 OPTIONS 当非法方法过滤 - 最简验证:用 curl 直连 PHP-FPM(绕过 Web 服务器),看
OPTIONS是否能进框架



















