Yii2 设置跨域 [ 技术分享 ]
设置跨域
Yii2 的跨域设置是非常便捷的,只需要设置 behaviors 中的 corsFilter 即可。
<?php
namespace api\controllers;
use common\web\CompositeAuth;
use yii\filters\Cors;
use yii\filters\auth\HttpBearerAuth;
use yii\rest\Controller;
/**
* 基础校验控制
*
* @author vogin
*
*/
class BasicController extends Controller
{
public function behaviors ()
{
$behaviors = parent::behaviors();
unset($behaviors['authenticator']);
// 跨域设置
$behaviors['corsFilter'] = [
'class' => Cors::className()
];
// 校验 Authorization bearer
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
HttpBearerAuth::className()
]
];
return $behaviors;
}
}
问题
但是,有时候,怎么配置都达不到效果出现报错
Access to XMLHttpRequest at 'http://api.xxx.com' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
目前发现的原因有两个。
问题1
权鉴在跨域之前被设置,比如这样。先是 $behaviors['authenticator'],再者 $behaviors['corsFilter'],这样会导致先鉴权再跨域,所以需要将设置提前,也就是 "设置跨域" 那样设置
<?php
public function behaviors ()
{
$behaviors = parent::behaviors();
unset($behaviors['authenticator']);
// 校验 Authorization bearer
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
HttpBearerAuth::className()
]
];
// 跨域设置
$behaviors['corsFilter'] = [
'class' => Cors::className()
];
return $behaviors;
}
问题2
路由问题。
由于并非继承 ActiveController
,而是 yii\rest\Controller
,所以路由都是自行指定的。
跨域检测是由 OPTIONS
方法去探测的,所以可能是此方法没有着落。
比如下面的方式,我并未指定 OPTIONS
对应的路由,所以其会报错
<?php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
// 获取所有标签
'GET v1/tags' => 'v1/tag/all',
// 获取单个标签
'GET v1/tags/<id:\d+>' => 'v1/tag/one',
// 添加单个标签
'POST v1/tags' => 'v1/tag/add',
// 编辑单个标签
'PUT v1/tags' => 'v1/tag/edit',
// 删除单个标签
'DELETE v1/tags' => 'v1/tag/del',
]
],
解决此问题需要指定 OPTIONS,并且添加对应的方法
路由
<?php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
// options 检测
'OPTIONS v1/tags' => 'v1/tag/options',
]
],
公共控制器中,增加 OPTIONS
,有几个模块,加几次
<?php
/**
* 基础校验控制
*
* @author vogin
*
*/
class BasicController extends Controller
{
public function actions ()
{
return [
'options' => [
'class' => 'yii\rest\OptionsAction'
]
];
}
// ......
}
其他方案
那就直接在 index.php 的最上面把 php 跨域的代码写上
<?php
header('Content-Type: text/html;charset=utf-8');
header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); // 允许请求的类型
header('Access-Control-Allow-Credentials: true'); // 设置是否允许发送 cookies
header('Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin'); // 设置允许自定义请求头的字段
如何排查
断点
最好的排查方式就是打断点,OPTIONS
也是一个完整的请求,在 ide
上使用 xdebug
断点能快速调试
共 0 条回复
没有找到数据。
蓝色主旋律
注册时间:2018-05-24
最后登录:2022-10-01
在线时长:95小时30分
最后登录:2022-10-01
在线时长:95小时30分
- 粉丝5
- 金钱16580
- 威望180
- 积分19330