浏览器卡在options预检阶段因thinkphp未正确处理,需确保app/middleware.php中严格注册think\middleware\cors::class且位置靠前;多应用模式须在对应应用配置;nginx需透传origin头。

前端发 POST 或带自定义 Header 的请求时,浏览器卡在 OPTIONS 预检阶段,返回 404 或 500,说明预检请求根本没被 ThinkPHP 正确拦截和响应。
确认内置 Cors 中间件是否已注册并前置
打开 app/middleware.php,检查全局中间件数组是否包含 【think\middleware\Cors::class】,且位置靠前(建议放在第 2 或第 3 位)——它必须在 Session、JWT 验证等业务中间件之前执行,否则预检请求可能被提前终止。
若写成 'cors' 或 CorsMiddleware::class,中间件将完全不生效;必须严格使用官方类名 think\middleware\Cors::class。
多应用模式下,需在对应应用的 app/middleware.php 中配置,而非根目录下的全局配置文件。
手动补全 Access-Control-Allow-Headers 字段
方法一:修改内置 Cors 中间件参数(推荐用于简单场景)
编辑 app/middleware.php,将 Cors 类注册为带参数的闭包:
[\think\middleware\Cors::class, ['allowHeaders' => ['Content-Type', 'Authorization', 'X-Requested-With', 'X-Auth-Token']]]
注意:【一旦启用 credentials,allowHeaders 不能含 *,必须显式列出所有前端实际发送的 Header 字段】,漏一个或大小写不一致(如 x-auth-token 写成 X-Auth-Token)都会导致预检失败。
方法二:自定义中间件(精准控制,适用于复杂白名单或二级域名场景)
在 app/middleware/ 下新建 CorsHeader.php:
第一步:在 handle 方法开头判断是否为 OPTIONS 请求:if ($request->isOptions()) { return response('', 204); }
第二步:调用 $next($request) 获取响应后,再设置头:$response = $next($request);$origin = $request->header('origin');if (in_array($origin, ['https://admin.example.com', 'https://app.example.com'])) { $response->header('Access-Control-Allow-Origin', $origin); $response->header('Access-Control-Allow-Credentials', 'true');}
第三步:统一设置允许方法与头部:$response->header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');$response->header('Access-Control-Allow-Headers', 'Content-Type,Authorization,X-Requested-With,X-Auth-Token');return $response;
验证 Nginx 是否透传 Origin 头
如果启用了 Nginx 反向代理,需确保其未过滤或覆盖 Origin 请求头——在 server 块中添加:proxy_set_header Origin $http_origin;
否则,即使中间件逻辑正确,$request->header('origin') 也会为空,导致动态 Origin 校验失效。
这一步操作起来很简单,直接把配置加进 Nginx 的 location 块就行。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











