En-têtes de requête Cross-Origin (CORS) avec en-têtes PHP

146

J'ai un script PHP simple que j'essaye une requête CORS inter-domaines:

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
...

Pourtant, j'obtiens toujours l'erreur:

Le champ d'en-tête de la demande X-Requested-Withn'est pas autorisé parAccess-Control-Allow-Headers

Quelque chose me manque?

Machavity
la source

Réponses:

59

Access-Control-Allow-Headersn'autorise pas *comme valeur acceptée, consultez la documentation de Mozilla ici .

Au lieu de l'astérisque, vous devez envoyer les en-têtes acceptés (d'abord X-Requested-Withcomme le dit l'erreur).

KARASZI István
la source
289

La gestion correcte des requêtes CORS est un peu plus complexe. Voici une fonction qui répondra plus complètement (et correctement).

/**
 *  An example CORS-compliant method.  It will allow any GET, POST, or OPTIONS requests from any
 *  origin.
 *
 *  In a production environment, you probably want to be more restrictive, but this gives you
 *  the general idea of what is involved.  For the nitty-gritty low-down, read:
 *
 *  - https://developer.mozilla.org/en/HTTP_access_control
 *  - http://www.w3.org/TR/cors/
 *
 */
function cors() {

    // Allow from any origin
    if (isset($_SERVER['HTTP_ORIGIN'])) {
        // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
        // you want to allow, and if so:
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }

    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            // may also be using PUT, PATCH, HEAD etc
            header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

        exit(0);
    }

    echo "You have CORS!";
}
arme à feu
la source
32
Notez que le renvoi de la valeur HTTP Origin comme origine autorisée permettra à quiconque de vous envoyer des demandes avec des cookies, volant ainsi potentiellement une session d'un utilisateur qui s'est connecté à votre site puis a consulté la page d'un attaquant. Vous souhaitez soit envoyer '*' (ce qui interdira les cookies empêchant ainsi le vol de session) ou les domaines spécifiques pour lesquels vous souhaitez que le site fonctionne.
Jules
1
D'accord. En pratique, vous n'autoriseriez probablement pas n'importe quel ancien domaine à utiliser votre service CORS, vous le limiteriez à un ensemble auquel vous avez décidé de faire confiance.
slashingweapon
Pour info, cette solution ne fonctionnait que pour moi dans un Linux server, IISpour une raison quelconque, ne fonctionnait tout simplement pas, je ne sais pas si c'est mon hébergement ou simplement si elle ne convient pasIIS
ncubica
1
Je vous remercie! Vous devez mettre cette réponse dans vos favoris. Dommage que nous ne puissions pas marquer cela comme une nouvelle réponse
Ascherer
1
Le seul qui fonctionne vraiment! .. Il suffit de changer Access-Control-Allow-Origin: * TO Access-Control-Allow-Origin: {$ _SERVER ['HTTP_ORIGIN']}
Renan Franca
60

J'ai eu la même erreur et je l'ai corrigée avec le PHP suivant dans mon script back-end:

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

header('Access-Control-Allow-Methods: GET, POST');

header("Access-Control-Allow-Headers: X-Requested-With");
Fiach Reid
la source
35

De nombreuses descriptions sur Internet ne mentionnent pas qu'il Access-Control-Allow-Originne suffit pas de spécifier . Voici un exemple complet qui fonctionne pour moi:

<?php
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, GET, DELETE, PUT, PATCH, OPTIONS');
        header('Access-Control-Allow-Headers: token, Content-Type');
        header('Access-Control-Max-Age: 1728000');
        header('Content-Length: 0');
        header('Content-Type: text/plain');
        die();
    }

    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/json');

    $ret = [
        'result' => 'OK',
    ];
    print json_encode($ret);
Csongor Halmai
la source
1
S'il vous plaît expliquer pourquoi il ne suffit pas et quel exemple minimal est suffisant.
halfpastfour.am
Malheureusement, je ne me souviens pas exactement et je n'ai pas le temps maintenant d'enquêter à nouveau mais, autant que je me souvienne, il y avait des hypothèses de base du côté du serveur Web / du navigateur qui l'empêchaient de fonctionner. C'était le code minimal qui fonctionnait pour moi.
Csongor Halmai
24

J'ai simplement réussi à faire fonctionner dropzone et d'autres plugins avec ce correctif (backend angularjs + php)

 header('Access-Control-Allow-Origin: *'); 
    header("Access-Control-Allow-Credentials: true");
    header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
    header('Access-Control-Max-Age: 1000');
    header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

ajoutez-le dans votre upload.php ou là où vous enverriez votre demande (par exemple si vous avez upload.html et que vous devez joindre les fichiers à upload.php, puis copiez et collez ces 4 lignes). De plus, si vous utilisez des plugins / addons CORS dans chrome / mozilla, assurez-vous de les basculer plusieurs fois, afin que CORS soit activé.

Fedeco
la source
15

Si vous souhaitez créer un service CORS à partir de PHP, vous pouvez utiliser ce code comme première étape de votre fichier qui gère les requêtes:

// Allow from any origin
if(isset($_SERVER["HTTP_ORIGIN"]))
{
    // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
}
else
{
    //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
    header("Access-Control-Allow-Origin: *");
}

header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 600");    // cache for 10 minutes

if($_SERVER["REQUEST_METHOD"] == "OPTIONS")
{
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    //Just exit with 200 OK with the above headers for OPTIONS method
    exit(0);
}
//From here, handle the request as it is ok
Finn Johansen
la source
8

CORS peut devenir un casse-tête, si nous ne comprenons pas correctement son fonctionnement. Je les utilise en PHP et ils fonctionnent sans problème. référence ici

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 1000");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
header("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE");
teintes3002
la source
7

Ce code fonctionne pour moi lorsque j'utilise angular 4 comme côté client et PHP comme côté serveur.

header("Access-Control-Allow-Origin: *");
Labib Hussain
la source
3

cela devrait fonctionner

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
user8453321
la source
0

ajoutez ce code dans .htaccess

ajouter des clés d'authentification personnalisées dans l'en-tête comme app_key, auth_key..etc

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers: "customKey1,customKey2, headers, Origin, X-Requested-With, Content-Type, Accept, Authorization"
Rakyesh Kadadas
la source
-1

Sous Windows, collez cette commande dans la fenêtre d' exécution juste le temps de tester le code

chrome.exe --user-data-dir = "C: / Chrome dev session" --disable-web-security

Fazil Raza
la source
Désactiver la sécurité Web de votre navigateur, même temporairement, est une mauvaise idée
Machavity