CORS - Comment faire un «contrôle en amont» d'une httprequest?

94

J'essaie de faire une requête HTTP interdomaine au service WCF (que je possède). J'ai lu plusieurs techniques pour travailler avec les limitations de scripts interdomaines. Étant donné que mon service doit accueillir à la fois les requêtes GET et POST, je ne peux pas implémenter une balise de script dynamique dont le src est l'URL d'une requête GET. Étant donné que je suis libre d'apporter des modifications au serveur, j'ai commencé à essayer de mettre en œuvre une solution de contournement qui consiste à configurer les réponses du serveur pour inclure l'en-tête "Access-Control-Allow-Origin" et les demandes de contrôle en amont avec et OPTIONS request. J'ai eu l'idée de ce post: faire fonctionner CORS

Du côté serveur, ma méthode Web ajoute «Access-Control-Allow-Origin: *» à la réponse HTTP. Je peux voir que les réponses incluent maintenant cet en-tête. Ma question est la suivante: Comment puis-je effectuer le «contrôle en amont» d'une demande (OPTIONS)? J'utilise jQuery.getJSON pour faire la demande GET mais le navigateur annule la demande tout de suite avec le tristement célèbre:

Origin http: // localhost n'est pas autorisé par Access-Control-Allow-Origin

Quelqu'un est-il familier avec cette technique CORS? Quels changements doivent être apportés au client pour contrôler en amont ma demande?

Merci!

pseudo
la source

Réponses:

158

Pendant la demande de contrôle en amont, vous devriez voir les deux en-têtes suivants: Access-Control-Request-Method et Access-Control-Request-Headers. Ces en-têtes de demande demandent au serveur des autorisations pour effectuer la demande réelle. Votre réponse en amont doit reconnaître ces en-têtes pour que la demande réelle fonctionne.

Par exemple, supposons que le navigateur effectue une requête avec les en-têtes suivants:

Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

Votre serveur doit alors répondre avec les en-têtes suivants:

Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

Portez une attention particulière à l'en-tête de réponse Access-Control-Allow-Headers. La valeur de cet en-tête doit être les mêmes en-têtes dans l'en-tête de demande Access-Control-Request-Headers, et il ne peut pas être «*».

Une fois que vous avez envoyé cette réponse à la demande de contrôle en amont, le navigateur effectuera la demande réelle. Vous pouvez en savoir plus sur CORS ici: http://www.html5rocks.com/en/tutorials/cors/

Monsur
la source
pouvez-vous ajouter plusieurs domaines à Access-Control-Allow-Origin?
botbot
@botbot Vous avez probablement déjà résolu le problème, mais au cas où d'autres se demanderaient le faireAccess-Control-Allow-Origin: *
Steve Chambers
2
J'ai peut-être raté quelque chose. Dois-je donc envoyer deux requêtes XMLHttp? Un pour le contrôle en amont; vérifier la réponse en cas de succès, puis envoyer la requête réelle?
Kangkan
14
@Kangkan, vous n'avez pas à vous soucier d'envoyer la demande de contrôle en amont. Si la demande nécessite un contrôle en amont, le navigateur l'enverra pour vous.
monsur
4
MERCI pour le peu `` prêter une attention particulière '' ... qui a résolu mon problème avec node / expressjs J'ai pu ajouter un filtre pour attraper ces demandes de contrôle en amont//cors and preflight filtering app.all('*', function(req, res, next){.. //preflight needs to return exact request-header res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers']); if ('OPTIONS' == req.method) return res.send(204);next(); });
Kurtfm
0

Bien que ce fil remonte à 2014, le problème peut toujours être d'actualité pour beaucoup d'entre nous. Voici comment je l'ai traité dans un contexte jQuery 1.12 / PHP 5.6:

  • jQuery a envoyé sa requête XHR en utilisant uniquement des en-têtes limités; seule «Origine» a été envoyée.
  • Aucune demande de contrôle en amont n'était nécessaire.
  • Le serveur n'avait qu'à détecter une telle requête, et ajouter le "Access-Control-Allow-Origin:". $ _SERVER ['HTTP_ORIGIN'] en-tête, après avoir détecté qu'il s'agissait d'un XHR d'origine croisée.

Exemple de code PHP:

if (!empty($_SERVER['HTTP_ORIGIN'])) {
    // Uh oh, this XHR comes from outer space...
    // Use this opportunity to filter out referers that shouldn't be allowed to see this request
    if (!preg_match('@\.partner\.domain\.net$@'))
        die("End of the road if you're not my business partner.");

    // otherwise oblige
    header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
}
else {
    // local request, no need to send a specific header for CORS
}

En particulier, n'ajoutez pas un exit;car aucun contrôle en amont n'est nécessaire.

Fabien Haddadi
la source