yii2表单json验证跨域问题需四步解决:设response::format_json与正确content-type头;显式处理options请求并跳过鉴权;配置jsonparser解析器并用bodyparams取参;cors中origin禁用*且access-control-request-headers列全实际请求头。

Yii2 表单验证返回 JSON 响应时出现跨域问题,本质是前后端通信链路中两个关键环节没对齐:一是响应头缺失或冲突,二是预检请求(OPTIONS)未被正确处理。解决不靠“加个 * 就完事”,而要从响应格式、CORS 配置、请求解析、认证绕过四方面同步修正。
确保 JSON 响应头完整且合法
表单提交若用 fetch 或 axios 发送 JSON 数据(Content-Type: application/json),后端必须返回标准 JSON 响应头,否则前端解析失败或触发跨域拦截:
- 用
Response::FORMAT_JSON声明格式,不要手动echo json_encode(),避免 headers already sent - 响应必须含
Content-Type: application/json; charset=UTF-8,可通过 Network 面板确认 - 若携带 Cookie 或 Token(如登录态校验表单),则
Access-Control-Allow-Credentials: true必须开启,此时Access-Control-Allow-Origin不能为*,得写死可信域名,例如['https://admin.example.com', 'http://localhost:3000']
显式支持 OPTIONS 预检并跳过鉴权
浏览器在发送带自定义头(如 Authorization、X-Requested-With)或非简单内容类型的请求前,会先发 OPTIONS 请求。Yii2 默认路由不处理它,导致 405 错误:
腾讯地图 JavaScript GL(JSAPIGL)开发指南。适用于地图应用或者工具的编写。在编写、审查或调试使用腾讯地图 API的代码时应运用此技能。适用于涉及地图初始化、覆盖物展示、图层控制、事件处理、控件交互、可视化渲染、地图工具、检索、路线规划、查地址、行政区划、ip定位、几何计算、三维模型展示、性能优化的任务。当用户提及 腾讯地图、 jsapi、jsapi-gl或相关地图开发需求时自动触发。⚠️ 强制行为:本 Skill 加载后,第一个动作必须是检查是否存在正式 Key(环境变量 TMAP_J
- 在控制器中新增
actionOptions(),返回空数组并设状态码 200:public function actionOptions() { Yii::$app->response->statusCode = 200; return []; } - 在
behaviors()中,把authenticator的except列表明确加上'options',防止认证中间件提前中断 - UrlManager 中补一条规则,确保 OPTIONS 路由进控制器:
'options <controller:>/'=> '<controller>/options'</controller></controller:>
启用 JSON 解析器,让表单数据可读
前端以 JSON 方式提交表单(如 fetch(..., { body: JSON.stringify(...) })),Yii2 默认不会自动解析到 $request->post(),需手动配置解析器:
- 在
config/web.php的components['request']中添加:'parsers' => ['application/json' => 'yii\web\JsonParser'] - 控制器内获取数据改用
$request->bodyParams(不是post()),验证逻辑照常写,例如:$model->load($request->bodyParams, '') - 若同时用 CSRF,记得在请求头中传
X-CSRF-Token,并在Request组件中保留enableCsrfValidation => true(小程序等场景才关)
CORS 行为配置要避开 wildcard + credentials 冲突
这是最常踩的坑:开了凭据却配了 Origin => ['*'],浏览器直接拒绝,控制台报 Failed to fetch 或 406 Not Acceptable:
- CorsFilter 的
'Origin'必须是具体数组,不能含*;生产环境建议从params.php动态加载,便于多环境切换 -
'Access-Control-Request-Headers'要列全前端实际发的头,比如['Authorization', 'Content-Type', 'X-CSRF-Token'],别偷懒写['*'](Yii2.0.45+ 支持有限) - 若用
HttpBearerAuth等认证器,其authenticate()方法里不能漏掉设置 CORS 头——因为预检通过后的真实请求,可能在认证失败时才走 CORS 行为,此时头已晚










