web-dev-qa-db-fra.com

Le pré-vol CORS revient avec Access-Control-Allow-Origin: *, la requête du navigateur échoue

Déclencher une AJAX GET en http://qualifiedlocalhost:8888/resource.json déclenche le pré-vol attendu du CORS, qui semble bien revenir:

Demande OPTIONS avant le vol

Request URL:http://qualifiedlocalhost:8888/resource.json
Request Method:OPTIONS
Status Code:200 OK

En-têtes de demande

Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, Origin, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:qualifiedlocalhost:8888
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36

En-têtes de réponse

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:2
Content-Type:text/plain
Date:Thu, 01 Aug 2013 19:57:43 GMT
Set-Cookie:connect.sid=s%3AEpPytDm3Dk3H9V4J9y6_y-Nq.Rs572s475TpGhCP%2FK%2B2maKV6zYD%2FUg425zPDKHwoQ6s; Path=/; HttpOnly
X-Powered-By:Express

Vous cherchez bien?

Donc ça devrait marcher, non?

Mais la requête suivante échoue toujours avec l'erreur XMLHttpRequest cannot load http://qualifiedlocalhost:8888/resource.json. Origin http://localhost:9000 is not allowed by Access-Control-Allow-Origin.

Vraie demande

Request URL:http://qualifiedlocalhost:8888/resource.json

En-têtes de demande

Accept:application/json, text/plain, */*
Cache-Control:no-cache
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36
X-Requested-With:XMLHttpRequest

Aidez-moi!

Peut-être qu'il regarde juste devant moi. Mais, des idées? Juste au cas où cela serait pertinent ... J'utilise un $resource AngularJS et je parle à un serveur CompoundJS.

19
tnunamak

changer vos méthodes d'accès-contrôle-autoriser: 'GET, POST' à 'GET, POST, PUT, DELETE'

avant:

   app.use(function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
        next();
    });

Après:

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    next();
});
13
KARTHIKEYAN.A

J'ai récemment eu le même problème . Le problème est que l'en-tête Access-Control-Allow-Origin (et, si vous l'utilisez, l'en-tête Access-Control-Allow-Credentials) doit être envoyé dans both la réponse de contrôle en amont et la réponse réelle.

Votre exemple ne l’a que dans la réponse de contrôle en amont.

Est-ce que votre fonction serveur/get Web inclut AUSSI l'en-tête HTTP: Access-Control-Allow-Origin? J'ai finalement trouvé le succès avec cet ajout, en utilisant AngularJS 1.0.7 et un servlet Java distant. Voici mon extrait de code Java - aucune modification n'a été requise dans le client AngularJS:

Servlet:

@Override
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // Send Response
    super.doOptions(request,  response);
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /* ... */
    response.setHeader("Access-Control-Allow-Origin", "*");
}

Une alternative plus élégante est un filtre de servlet.

5
Jeff Collier

Nous avons remarqué le même problème, où le serveur envoie les en-têtes CORS corrects, mais le navigateur échoue car il pense que les exigences CORS ne sont pas satisfaites. Plus intéressant encore, dans notre cas, cela ne se produit que sur certains appels AJAX dans la même session de navigateur, mais pas tous.

Théorie de travail ...

Effacer le cache du navigateur résout le problème dans notre cas - Ma théorie de travail actuelle est que cela a quelque chose à voir avec les cookies installés par le serveur cross Origin. J'ai remarqué que dans votre scénario, un cookie est défini dans le cadre de la réponse à la demande OPTIONS avant le vol. Avez-vous essayé de faire en sorte que ce serveur ne mette pas de cookies pour les demandes provenant d'une origine différente?

Cependant, nous avons remarqué que, dans certains cas, le problème réapparaissait après la réinitialisation du navigateur. De plus, si vous exécutez le navigateur en mode privé, le problème disparaît, ce qui indique un problème lié au contenu du cache du navigateur.

Pour référence, voici mon scénario (j'ai presque posté ceci comme une nouvelle question dans SO, mais le mettant ici à la place):

Nous avons rencontré un bogue dans lequel certaines requêtes CORS GET effectuées via jQuery.ajax échouaient. Dans une session de navigateur donnée, nous voyons la demande OPTIONS pré-vol passer, suivie de la demande réelle. Dans la même session, certaines demandes sont traitées et d'autres échouent. 

La séquence de demandes et de réponses dans la console réseau du navigateur se présente comme suit:

D'abord la demande de pré-vol OPTIONS

OPTIONS /api/v1/users/337/statuses
HTTP/1.1 Host: api.obfuscatedserver.com 
Connection: keep-alive 
Access-Control-Request-Method: GET 
Origin: http://10.10.8.84:3003 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Access-Control-Request-Headers: accept, Origin, x-csrf-token, auth 
Accept: */* Referer: http://10.10.8.84:3003/ 
Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8

Ce qui obtient une réponse comme,

HTTP/1.1 200 OK 
Date: Tue, 06 Aug 2013 19:18:22 GMT 
Server: Apache/2.2.22 (Ubuntu) 
Access-Control-Allow-Origin: http://10.10.8.84:3003 
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT 
Access-Control-Max-Age: 1728000 
Access-Control-Allow-Credentials: true 
Access-Control-Allow-Headers: accept, Origin, x-csrf-token, auth 
X-UA-Compatible: IE=Edge,chrome=1 
Cache-Control: no-cache 
X-Request-Id: 4429c4ea9ce12b6dcf364ac7f159c13c 
X-Runtime: 0.001344 
X-Rack-Cache: invalidate, pass 
X-Powered-By: Phusion 
Passenger 4.0.2 
Status: 200 OK 
Vary: Accept-Encoding
Content-Encoding: gzip

Ensuite, la demande GET réelle,

GET https://api.obfuscatedserver.com/api/v1/users/337
HTTP/1.1 
Accept: application/json, text/javascript, */*; q=0.01 
Referer: http://10.10.8.84:3003/ 
Origin: http://10.10.8.84:3003 
X-CSRF-Token: xxxxxxx 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 
auth: xxxxxxxxx

Qui obtient une erreur dans la console du navigateur comme,

XMLHttpRequest
  cannot load https://api.obfuscatedserver.com/api/v1/users/337.
  Origin http://10.10.8.84:3003 is not allowed by Access-Control-Allow-Origin.

Débogage supplémentaire

Je peux rejouer la même séquence via curl et je vois des réponses valables venant du serveur. c'est-à-dire qu'ils ont les en-têtes CORS attendus qui devraient laisser passer les demandes.

L'exécution du même scénario dans une fenêtre de navigateur privée/incognito ne reproduisait pas le problème. Cela m’a amené à essayer de vider la mémoire cache, ce qui a également permis de résoudre le problème. Mais après un moment, il est revenu.

Le problème se reproduisait sur un safari sur iPhone ainsi que sur Chrome sur le bureau OSX.

Ce dont j'ai vraiment besoin d'aide

Je soupçonne que certains cookies installés dans le domaine cross-Origin sont impliqués et sont susceptibles de révéler un bogue dans le navigateur. Existe-t-il des outils ou des points d'arrêt que je peux définir dans le navigateur (pile native?) Pour essayer de déboguer davantage? Un point d'arrêt dans le code qui évalue la stratégie CORS serait idéal.

3
Shyam Habarakada

utiliser le module cors pour éviter le problème

var cors = require('cors')

var app = express()
app.use(cors())
0
KARTHIKEYAN.A

On dirait que votre réponse aux "options" fonctionne bien. Le problème semble être dans la réponse «obtenir».

Vous voudrez que votre réponse «get» renvoie les mêmes en-têtes CORS que la réponse «options». 

En particulier, la réponse «get» devrait inclure

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*
0
Larry Kang