web-dev-qa-db-fra.com

La requête CORS échoue dans Chrome uniquement si des en-têtes sont disponibles.

J'essaie d'envoyer une demande CORS simple au serveur d'applications externe qui utilise une clé de session pour l'autorisation.

$.ajax({
    type: "GET",
    url: "https://192.168.1.72:8442/api/file/",
    headers: {"Authorization": "3238562439e44fcab4036a24a1e6b0fb"}
});

Cela fonctionne bien dans Firefox 18, Opera 12.12 et Rekonq 2.0 (utilise également WebKit) mais ne fonctionne pas dans Google Chrome (versions 21 et 24 essayées). Dans Google Chrome, il indique que le chargement des ressources dans OPTIONS a échoué dans Network Inspector et que le serveur d'applications ne reçoit aucune demande. J'ai essayé jQuery 1.8.3 et 1.9.0.

Request URL:https://192.168.1.72:8442/api/file/
Request Headers
Access-Control-Request-Headers:accept, authorization, Origin
Access-Control-Request-Method:GET
Cache-Control:no-cache
Origin:https://192.168.1.72:8480
Pragma:no-cache

Si je supprime les en-têtes de la demande, je reçois également 401 également dans Google Chrome et celui-ci peut accéder à la ressource en cas d'autorisation est désactivé sur le serveur d'applications. Peu importe les en-têtes envoyés. Seul l'en-tête que je peux envoyer est {"Content-Type": "plain/text"}. Tous les autres noms/valeurs d'en-tête génèrent une erreur dans Google Chrome mais fonctionnent dans tous les navigateurs que j'ai mentionnés ci-dessus.

Pourquoi Google Chrome ne gère-t-il pas les en-têtes dans les demandes CORS?

14
Karmo Rosental
16
Karmo Rosental

J'utilise un certificat auto-signé sur mon serveur api et cela semble être le problème. J'ai constaté que si je lance Google Chrome avec l'option --disable-web-security, CORS avec les en-têtes de demande fonctionne. Sans --disable-web-security, je peux envoyer des demandes CORS au serveur api auto-signé mais je ne peux ajouter aucun en-tête (sauf Content-Type).

3
Karmo Rosental

J'ai trouvé qu'Access-Control-Allow-Headers: * devrait être réglé UNIQUEMENT pour la requête "OPTIONS". Si vous le renvoyez pour la demande POST, le navigateur annule la demande (au moins pour chrome )

Le code PHP suivant fonctionne pour moi 

// Allow CORS
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Credentials: true');    
header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); 

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  header("Access-Control-Allow-Headers: *");
}

J'ai trouvé des questions similaires avec une réponse trompeuse: - Le fil du serveur indique qu'il s'agit d'un bogue de chrome datant de 2 ans: Access-Control-Allow-Headers ne correspond pas à localhost. C'est faux: je peux utiliser CORS sur mon serveur local avec Post normalement - Access-Control-Allow-Headers accepte les caractères génériques. C'est également faux, le joker fonctionne pour moi (j'ai testé uniquement avec Chrome)

Cela me prend une demi-journée pour comprendre le problème.

Code heureux

2
greensuisse

Côté serveur : Le serveur doit définir l'en-tête "Access-Control-Allow-Credentials" ainsi que les en-têtes autorisés dans "Access-Control-Allow-Headers".

Côté client : Vous pouvez définir xhrFields dans $ .ajax () au lieu de passer explicitement l'en-tête Auth.

xhrFields: {
    withCredentials: true 
}

Plus de détails ici .

1