Yii2 REST+ Angular 跨域 CORS [英] Yii2 REST+ Angular Cross Domain CORS

查看:25
本文介绍了Yii2 REST+ Angular 跨域 CORS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开发了 Angular &Yii2 REST 服务.跨域有问题.在下面添加我的角度 &Yii2 REST 代码.

I have developed Angular & Yii2 REST service. Have problem in cross domain. Here below add my angular & Yii2 REST Code.

AngularJs :(如'http://organization1.example.com','http://organization2.example.com',....)

AngularJs : (like 'http://organization1.example.com','http://organization2.example.com',....)

$http.defaults.useXDomain = true;
$http.defaults.withCredentials = true;
$http.defaults.headers.common['Authorization'] = 'Bearer ' + MYTOKEN

我来自 Angular 控制器的请求:

My Request from Angular Controller:

apiURL = 'http://api.example.com';
$http.get(apiURL + '/roles')
     .success(function (roles) { })
     .error(function () { });

Yii2 .htaccess:(REST URL 像 'http://api.example.com')

Yii2 .htaccess: (REST URL like 'http://api.example.com')

Header always set Access-Control-Allow-Origin: "*"
Header always set Access-Control-Allow-Credentials: true
Header always set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Authorization,X-Requested-With, content-type"

Yii2 我的行为:

public function behaviors() {
    $behaviors = parent::behaviors();
    $behaviors['corsFilter'] = [
        'class' => Cors::className(),
        'cors' => [
            'Origin' => ['*'],
            'Access-Control-Expose-Headers' => [
                'X-Pagination-Per-Page',
                'X-Pagination-Total-Count',
                'X-Pagination-Current-Page',
                'X-Pagination-Page-Count',
            ],
        ],
    ];
    $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'except' => ['options'],
    ];
    $behaviors['contentNegotiator'] = [
        'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
    ];

    return $behaviors;
}

问题

从我的角度请求是'GET'方法,但它会变成'OPTIONS'方法&返回 401 未经授权的错误(CORS).因为没有发送请求授权头.

From my angular request is 'GET' method, but it will goes 'OPTIONS' method & return 401 Unauthorized error(CORS). because the request Authorization header is not send.

推荐答案

更新:

正如@jlapoutre 所指出的,这在 中得到了很好的描述官方文档:

As pointed by @jlapoutre, this is now well described in official docs:

向控制器添加跨域资源共享过滤器是一个比添加上述其他过滤器要复杂一些,因为必须在身份验证之前应用 CORS 过滤器方法,因此需要与其他方法略有不同的方法过滤器.还必须为 CORS 预检禁用身份验证请求,以便浏览器可以安全地确定请求是否可以预先制作,无需发送认证证书.下面显示了添加所需的代码yiifiltersCors 过滤到现有的控制器,从yii estActiveController:

Adding the Cross-Origin Resource Sharing filter to a controller is a bit more complicated than adding other filters described above, because the CORS filter has to be applied before authentication methods and thus needs a slightly different approach compared to other filters. Also authentication has to be disabled for the CORS Preflight requests so that a browser can safely determine whether a request can be made beforehand without the need for sending authentication credentials. The following shows the code that is needed to add the yiifiltersCors filter to an existing controller that extends from yii estActiveController:

use yiifiltersauthHttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();

    // remove authentication filter
    $auth = $behaviors['authenticator'];
    unset($behaviors['authenticator']);

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => yiifiltersCors::className(),
    ];

    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];

    return $behaviors;
}

<小时>

旧答案 (已弃用)

parent::behaviors() 合并时存在排序问题.完整详情此处.

There is an ordering issue when merging with parent::behaviors(). Full details here.

我建议在与父数组合并时不要定义键:

I would recommend not defining keys when merging with parent array:

public function behaviors()
{
    return yiihelpersArrayHelper::merge([
        [
            'class' => yiifiltersCors::className(),
            'cors' => [...],
        ],
        [
            'class' => yiifiltersauthHttpBearerAuth::className(),
            'except' => ['options'],
        ],
        [
            'class' => ContentNegotiator::className(),
            'formats' => [...],
        ]
    ], parent::behaviors());
}

这篇关于Yii2 REST+ Angular 跨域 CORS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆