2016-02-12 25 views
5

Ho sviluppato il servizio angolare & Yii2 REST. Hai problemi nel dominio incrociato. Qui di seguito aggiungo il mio angolare & Codice REST Yii2.YII REST + Angular Cross Domain CORS

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

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

mia richiesta dal controller angolare:

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

Yii2 .htaccess: (REST URL del tipo ' 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 mio comportamento:

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

Problema

Dalla mia richiesta angolare è 'GET' metodo, ma lo farà va metodo 'Opzioni' & tornare errore 401 non autorizzato (CORS). perché l'intestazione Autorizzazione richiesta non viene inviata.

risposta

0

nel controller:

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

Aggiornamento:

Come sottolineato da @jlapoutre, questo è ormai ben descritto in official docs:

Aggiunta la Croce -Origin filtro di condivisione risorse a un controller è un bit più complicato dell'aggiunta di altri filtri sopra descritti, perché il filtro CORS deve essere applicato prima dei metodi di autenticazione e quindi richiede un approccio leggermente diverso rispetto agli altri filtri . Anche l'autenticazione deve essere disabilitata per le richieste CORS Preflight in modo che un browser possa determinare in modo sicuro se una richiesta può effettuare in anticipo senza la necessità di inviare credenziali di autenticazione . Quanto segue mostra il codice che è necessario per aggiungere le Yii \ filtri \ Cors filtro a un controller esistente che si estende dalla Yii \ riposo \ 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; 
} 

Vecchio Risposta(obsoleto)

Si verifica un problema di ordinamento durante l'unione con parent::behaviors(). Tutti i dettagli here.

Raccomando di non definire tasti quando la fusione con array di genitore:

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

Questo è ora documentato chiaramente qui: http://www.yiiframework.com/doc-2.0/guide-rest-controllers.html # cors - basta seguire questa guida e funzionerà. Riepilogo: assicurati che l'autenticazione venga dopo il comportamento CORS ed escluda OPZIONI dall'autenticazione in qualsiasi momento. – jlapoutre

+0

aggiornato. grazie @jlapoutre –

Problemi correlati