web-dev-qa-db-fra.com

CORS: PHP: La réponse à la demande de contrôle en amont ne passe pas. Suis l'origine

Donc, je sais qu'il y a beaucoup de messages CORS là-bas, et j'y ajoute juste, mais je ne trouve aucun avec des réponses qui m'aident. Je construis donc une application angular 4 qui repose sur mon api php. Travailler localement c'est bien, au moment où je la lance sur le domaine avec l'application à app.example.com, et l'api à api.example.com, Je ne parviens pas à dépasser ma connexion, car j'obtiens l'erreur suivante:

XMLHttpRequest ne peut pas charger http://api.example.com/Account/Login . La réponse à la demande de contrôle en amont ne passe pas la vérification du contrôle d'accès: aucun en-tête "Access-Control-Allow-Origin" n'est présent sur la ressource demandée. L'origine ' http://app.example.com ' n'est donc pas autorisée à accéder.

Mon code php ressemble à ceci:

$http_Origin = $_SERVER['HTTP_Origin'];

$allowed_domains = array(
    'http://example.com',
    'https://example.com',
    'http://app.example.com',
    'https://app.example.com',
    'http://www.example.com',
    'https://www.example.com'
);

if (in_array(strtolower($http_Origin), $allowed_domains))
{  
    // header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Origin: $http_Origin");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
        header("Access-Control-Allow-Headers: Authorization, Content-Type,Accept, Origin");
    exit(0);
}

Mon Angular post ressemble à ceci:

public login(login: Login): Observable<LoginResponse> {
    let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Authorization', 'Basic ' + btoa(login.Username + ':' + login.Password));
    return  this.http.post(this.apiBaseUrl + '/Account/Login', "grant_type=client_credentials", { headers: headers })
        .map(response => {
            // code
        });
}

Si je lance la demande via postman, ce qui ne dérange pas avec CORS, j'obtiens:

{ "error": "invalid_client", "error_description": "Client credentials were not found in the headers or body" }

J'ai essayé de définir Origin sur '* 'juste pour tester et voir si c'était le cœur du problème, et cela échoue toujours de la même manière.

Modifier Mise à jour des informations ci-dessous. Changer le casse dans les en-têtes n'a eu aucun effet et retirer le code de leurs instructions if n'a eu aucun effet.

J'ai débogué le php en disant à mon application en direct d'aller sur mon api locale, et le php fonctionne comme prévu. Il définit les en-têtes et en fait chacune des instructions if.

Edit take 2 Je pourrais vraiment utiliser de l'aide sur celui-ci, si quelqu'un a des idées, je l'apprécie.

Edit take 3 Si je mets tous les trucs d'en-tête dans mon .htaccess plutôt que mon php, ça me laisse passer . Cependant, maintenant je suis bloqué sur l'erreur répertoriée ci-dessus que j'obtiens toujours lors de l'utilisation de postman, mais maintenant c'est lors de l'utilisation du site réel.

{"error":"invalid_client","error_description":"Client credentials were not found in the headers or body"}

Mes en-têtes de réponse sont comme ça

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:authorization, content-type, accept, Origin
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*

Je vais le changer de * à mes domaines uniquement une fois que je l'aurai fonctionné. Mais pour l'instant, je le laisse comme *.

Mes en-têtes comme demandé.

Headers for failed request

8
Nieminen

OK, j'ai eu des problèmes similaires récemment et j'ai tout résolu uniquement sur le côté backend sans trucs .htaccess.

lorsque le navigateur envoie des demandes inter-serveurs, il envoie d'abord une demande OPTIONS pour s'assurer qu'il est valide et qu'il peut envoyer la "vraie" demande. Après avoir obtenu une réponse correcte et valide de OPTIONS, alors seulement il envoie la "vraie" demande.

Maintenant, pour les deux requêtes sur le backend, vous devez vous assurer de renvoyer les en-têtes appropriés: type de contenu, allow-Origin, allow-headers, etc.

Assurez-vous que dans la demande OPTIONS sur le backend, l'application renvoie les en-têtes et renvoie la réponse, sans poursuivre le flux complet de l'application.

Dans la "vraie" demande, vous devez renvoyer les en-têtes appropriés et votre corps de réponse régulier.

exemple:

    //The Response object
    $res = $app->response;

    $res->headers->set('Content-Type', 'application/json');
    $res->headers->set('Access-Control-Allow-Origin', 'http://example.com');
    $res->headers->set('Access-Control-Allow-Credentials', 'true');
    $res->headers->set('Access-Control-Max-Age', '60');
    $res->headers->set('Access-Control-Allow-Headers', 'AccountKey,x-requested-with, Content-Type, Origin, authorization, accept, client-security-token, Host, date, cookie, cookie2');
    $res->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

    if ( ! $req->isOptions()) {
        // this continues the normal flow of the app, and will return the proper body
        $this->next->call();
    } else {
        //stops the app, and sends the response
        return $res;
    }

Choses à retenir:

  • si vous utilisez: "Access-Control-Allow-Credentials" = true assurez-vous que "Access-Control-Allow-Origin" n'est pas "*", il doit être défini avec un domaine approprié! (beaucoup de sang a été renversé ici: /)

  • définir les en-têtes autorisés que vous obtiendrez dans "Access-Control-Allow-Headers" si vous ne les définissez pas, la demande échouera

  • si vous utilisez "Authorization: Bearer", alors "Access-Control-Allow-Headers" devrait également contenir "Authorization", sinon, la demande échouera
6
Tzook Bar Noy

J'ai ajouté ci-dessous en php et cela a résolu mon problème.

header("Access-Control-Allow-Origin: *");

header("Access-Control-Allow-Headers: Content-Type, Origin");
3
Piyush

J'ai eu un problème similaire,

Environnement de développement: serveur Web Apache derrière NginX Proxy

Mon application se trouve dans un hôte virtuel sur mon serveur Apache, configuré avec le nom: appname.devdomain.com

Lors de l'accès à une application Web en interne, je ne passais pas par le proxy: j'utilisais l'url: appname.devdomain.com

Je n'ai eu aucun problème de cette façon.

Mais, lorsque vous y accédez en externe en utilisant l'url publique: appname.prddomain.com, il se charge, a même accès au système après la connexion, puis charge les modèles et du contenu de session, puis, si un appel asynchrone est effectué par le client, alors Je recevrais le message suivant dans la console chrome console:

"Access to XMLHttpRequest at 'http://appname.devdomain.com/miAdminPanel.php' from Origin 'http://appname.prddomain.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request."

Pour tester cela, j'ai ouvert deux onglets

Le premier onglet a accédé au Web en utilisant url: appname.devdomain.com, fait XMLHttpRequest -> OK

Le deuxième onglet a accédé au Web en utilisant url: appname.prddomain.com, fait le message d'erreur XMLHttpRequest -> CORS ci-dessus.

Ainsi, après avoir modifié la configuration du proxy Nginx:

server {
    listen      80;
    server_name appname.prddomain.com;

    # SSL log files ###
    access_log      /path/to/acces-log.log;
    error_log       /path/to/error-log.log;

location / {
    proxy_pass  http://appname.devdomain.com;
    proxy_set_header X-Forwarded-Host $Host;
    proxy_set_header X-Forwarded-Server $Host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

fondamentalement, cela indique au proxy de traiter la demande externe comme une demande interne.

0
1rx