2016-02-12 97 views
5

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

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

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

我的要求,从角控制器:

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

Yii2的.htaccess:(REST URL像“ 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' 的方法,但它会进入 '选项' 方法&返回401未经授权错误(CORS)。因为请求授权标头不发送。

回答

0

在你的控制器:

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()); 
} 

Documentation

7

更新:

正如指出的@jlapoutre,这是现在很好的描述in official docs

添加交叉-Origin资源共享过滤器控制器比添加上述其他过滤器 更复杂一点,因为必须在认证 方法之前应用CORS过滤器,因此需要与其他 过滤器稍微不同的方法。还需要禁用CORS预检 请求的身份验证,以便浏览器可以安全地确定是否可以预先请求 ,而无需发送身份验证 凭证。下面显示\一个Cors过滤到从 YII \其余\ ActiveController延伸的现有控制器需要添加 YII \过滤器的代码:

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()合并时有订购问题。全部细节here

我会建议与父阵列合并时,如果不定义键:

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()); 
} 
+1

现在这是记录在这里明确:http://www.yiiframework.com/doc-2.0/guide-rest-controllers。html#cors - 只要按照这个指南,它会工作。总结:确保CORS行为之后进行身份验证,并始终从身份验证中排除OPTIONS。 – jlapoutre

+0

已更新。谢谢@jlapoutre –