繁体   English   中英

Yii2 REST + Angular Cross Domain CORS

[英]Yii2 REST+ Angular Cross Domain CORS

我开发了Angular和Yii2 REST服务。 在跨域有问题。 下面添加我的angular&Yii2 REST代码。

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

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

我来自Angular Controller的请求:

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

Yii2 .htaccess :( REST网址如' 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 Unauthorized error(CORS)。 因为请求Authorization标头不发送。

更新:

正如@jlapoutre所指出的,现在官方文档中对此进行了详细描述:

将交叉源资源共享过滤器添加到控制器比添加上述其他过滤器要复杂一些,因为必须在认证方法之前应用CORS过滤器,因此与其他过滤器相比需要稍微不同的方法。 此外,还必须为CORS预检请求禁用身份验证,以便浏览器可以安全地确定是否可以事先进行请求,而无需发送身份验证凭据。 下面显示了将yii \\ filters \\ Cors过滤器添加到从yii \\ rest \\ ActiveController扩展的现有控制器所需的代码:

 use yii\\filters\\auth\\HttpBasicAuth; public function behaviors() { $behaviors = parent::behaviors(); // remove authentication filter $auth = $behaviors['authenticator']; unset($behaviors['authenticator']); // add CORS filter $behaviors['corsFilter'] = [ 'class' => \\yii\\filters\\Cors::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()合并时存在排序问题。 详情请点击此处

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

public function behaviors()
{
    return \yii\helpers\ArrayHelper::merge([
        [
            'class' => \yii\filters\Cors::className(),
            'cors' => [...],
        ],
        [
            'class' => \yii\filters\auth\HttpBearerAuth::className(),
            'except' => ['options'],
        ],
        [
            'class' => ContentNegotiator::className(),
            'formats' => [...],
        ]
    ], parent::behaviors());
}

在你的控制器中:

use yii\filters\Cors;
...
public function behaviors()
{
    return array_merge([
        'cors' => [
            'class' => Cors::className(),
            #special rules for particular action
            'actions' => [
                'your-action-name' => [
                    #web-servers which you alllow cross-domain access
                    'Origin' => ['*'],
                    'Access-Control-Request-Method' => ['POST'],
                    'Access-Control-Request-Headers' => ['*'],
                    'Access-Control-Allow-Credentials' => null,
                    'Access-Control-Max-Age' => 86400,
                    'Access-Control-Expose-Headers' => [],
                ]
            ],
            #common rules
            'cors' => [
                'Origin' => [],
                'Access-Control-Request-Method' => [],
                'Access-Control-Request-Headers' => [],
                'Access-Control-Allow-Credentials' => null,
                'Access-Control-Max-Age' => 0,
                'Access-Control-Expose-Headers' => [],
            ]
        ],
    ], parent::behaviors());
}

文档

你的代码问题,你一开始就没有取消认证

public function behaviors() {
$behaviors = parent::behaviors();
/*unset here*/
unset($behaviors['authenticator']);
$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',
        ],
    ],
];
/*re-set here*/
$behaviors['authenticator'] = [
    'class' => HttpBearerAuth::className(),
    'except' => ['options'],
];
$behaviors['contentNegotiator'] = [
    'class' => ContentNegotiator::className(),
    'formats' => [
        'application/json' => Response::FORMAT_JSON,
    ],
];

return $behaviors;

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM