2016-02-12 2 views
5

Я разработал Angular & Yii2 REST сервис. Возникли проблемы в перекрестном домене. Здесь ниже добавьте мой угловой код & Yii2 REST.Yii2 REST + Angular Cross Domain 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' метод, но он будет идет метод 'OPTIONS' & вернуть 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

Update:

Как указано на @jlapoutre, теперь это хорошо описано in official docs:

Добавление Креста -Origin Resource Sharing фильтр для контроллер представляет собой бит , более сложный, чем добавление других фильтров, описанных выше, , потому что фильтр CORS должен применяться перед аутентификацией и, следовательно, необходим несколько иной подход по сравнению с другими фильтрами . Кроме того, аутентификация должна быть отключена для запросов CORS Preflight , чтобы браузер мог безопасно определить, может ли быть выполнен запрос без необходимости отправки аутентификации. учетные данные. Ниже приведен код, который необходим для добавления YII \ фильтры \ Co фильтра к существующему контроллеру, который простирается от YII \ остального \ 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() возникает проблема с заказом. Полная информация 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 –