2016-02-12 43 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 –