web-dev-qa-db-fra.com

Yii2 cors filtre l'erreur selon laquelle aucun en-tête «Access-Control-Allow-Origin» n'est présent

Cette question j'ai défini le comportement de mon contrôleur de repos comme

public function behaviors()
{
    $behaviors = parent::behaviors();

    $auth= $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'only' => ['dashboard'],
    ];
    $behaviors['contentNegotiator'] = [
        'class' => ContentNegotiator::className(),
        'formats' => [
            'application/json' => Response::FORMAT_JSON,
        ],
    ];
    $acces=$behaviors['access'] = [
        'class' => AccessControl::className(),
        'only' => ['login'],
        'rules' => [
            [
                'actions' => ['login'],
                'allow' => true,
                'roles' => ['?'],
            ],
        ],
    ];

    unset($behaviors['authenticator']);
    unset($behaviors['access']);

Et maintenant les filtres cors

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
          'cors' => [
        // restrict access to
        'Access-Control-Allow-Origin' => ['*'],
        'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
        // Allow only POST and PUT methods
        'Access-Control-Request-Headers' => ['*'],
        // Allow only headers 'X-Wsse'
        'Access-Control-Allow-Credentials' => true,
        // Allow OPTIONS caching
        'Access-Control-Max-Age' => 86400,
        // Allow the X-Pagination-Current-Page header to be exposed to the browser.
        'Access-Control-Expose-Headers' => [],
      ]
    ];

    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
       $behaviors['access'] = $access;
    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];
    return $behaviors;
}

Un front my angular2 comme

    const body = JSON.stringify(user);
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append('Content-Type', 'application/json');
headers.append('Access-Control-Allow-Credentials', "*");
return this._http.post(this.loginUrl, body, { headers:headers })
  .map((response: Response) => {
     //process response
  })
.catch(this.handleError);

Mais je reçois toujours une erreur de

Response to preflight request doesn't pass access control check: No
 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 
 'http://localhost:3000' is therefore not allowed access.

Quel pourrait être le problème depuis que j'ai mis le filtre cors dans les comportements yii2, désactivez l'authentificateur et l'ajouté plus tard Que puis-je manquer

J'ai également vérifié Ce lien et aussi celui-ci mais aucun ne résout le problème

15
Geoff

En cas de problème avec les en-têtes CORS, je recommande d'utiliser les instructions suivantes:

  1. Ajoutez la configuration de cors à votre contrôleur. Par exemple:

    /**
     * List of allowed domains.
     * Note: Restriction works only for AJAX (using CORS, is not secure).
     *
     * @return array List of domains, that can access to this API
     */
    public static function allowedDomains() {
        return [
            // '*',                        // star allows all domains
            'http://test1.example.com',
            'http://test2.example.com',
        ];
    }
    
    /**
     * @inheritdoc
     */
    public function behaviors() {
        return array_merge(parent::behaviors(), [
    
            // For cross-domain AJAX request
            'corsFilter'  => [
                'class' => \yii\filters\Cors::className(),
                'cors'  => [
                    // restrict access to domains:
                    'Origin'                           => static::allowedDomains(),
                    'Access-Control-Request-Method'    => ['POST'],
                    'Access-Control-Allow-Credentials' => true,
                    'Access-Control-Max-Age'           => 3600,                 // Cache (seconds)
                ],
            ],
    
        ]);
    }
    
  2. Le code ci-dessus ajoutera à la réponse en-têtes http spéciaux. Vérifiez les en-têtes http à l'aide des outils de débogage du navigateur:

  3. L'en-tête http de la demande doit contenir Origin. Il sera ajouté automatiquement par le navigateur sur Crossdomain AJAX. Cet en-tête http peut également être ajouté via votre bibliothèque JS. Sans cet en-tête http corsFilter ne fonctionnera pas.

    POST /api/some-method-name HTTP/1.1
    Host: api.example.com
    Connection: keep-alive
    Content-Length: 86
    Accept: */*
    Origin: https://my-site.example.com
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Referer: https://my-site.example.com/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,ru;q=0.4
    
  4. Les en-têtes http de réponse doivent contenir Access-Control-* en-têtes. Cet en-tête http sera ajouté par corsFilter.

    HTTP/1.1 200 OK
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: https://my-site.example.com
    Content-Type: application/json; charset=UTF-8
    Date: Fri, 24 Feb 2017 09:21:47 GMT
    Server: Apache
    Content-Length: 27
    Connection: keep-alive
    
  5. Si vous ne voyez pas ces en-têtes http en réponse , cela signifie probablement que \yii\filters\Cors ne fonctionne pas.

  6. Vérifiez les autres comportements/filtres dans le contrôleur. Essayez d'ajouter corsFilter comme premier comportement . Certains autres comportements empêchent probablement l'exécution de corsFilter.

  7. Essayez de désactiver la validation CSRF pour ce contrôleur (cela peut empêcher l'accès externe):

    /**
     * Controller for API methods.
     */
    class ApiController extends Controller
    {
    
        /**
         * @var bool See details {@link \yii\web\Controller::$enableCsrfValidation}.
         */
        public $enableCsrfValidation = false;
    
        // ...
    }
    
  8. En outre, vous devez vérifier votre serveur Web. Nginx peut probablement nécessiter une configuration supplémentaire, Apache peut nécessiter un redémarrage .

  9. Access-Control-* les en-têtes en réponse peuvent être ajoutés en utilisant un serveur web (voir pour Apache et nginx ). Mais je ne recommande pas d'utiliser cette méthode, car dans ce cas, vous ne pouvez pas gérer les utilisateurs http à l'aide d'une application.

  10. Quelques informations utiles peuvent être trouvées ici:

8
IStranger

Essaye ça :

public static function allowedDomains()
{
    return [
        // '*',                        // star allows all domains
        'http://localhost:3000',
        'http://test2.example.com',
    ];
}  



public function behaviors()
    {
        return array_merge(parent::behaviors(), [

            // For cross-domain AJAX request
            'corsFilter'  => [
                'class' => \yii\filters\Cors::className(),
                'cors'  => [
                    // restrict access to domains:
                    'Origin'                           => static::allowedDomains(),
                    'Access-Control-Request-Method'    => ['POST'],
                    'Access-Control-Allow-Credentials' => true,
                    'Access-Control-Max-Age'           => 3600,                 // Cache (seconds)

                ],
            ],

        ]);
    }

Ajoutez cette fonction sur votre contrôleur.

Et One Thing angular2 utilise la méthode OPTION pour la première fois.

4
Kakul Sarma

Le problème survient lorsque le frontend s'exécute dans un port autre que le port par défaut (80).

Ensuite, dans yii vous devez spécifier le port à travailler. Exemple: le frontend s'exécute à http: // localhost: 3000 in Yii cors set:

'Origin' => ['http: // localhost: 3000']

Si vous ne spécifiez pas le port (3000), Yii interprète le port par défaut et le résultat est:

'Origin' => ['http: // localhost: 80']
1
Dino Di Luca