Le caractère générique CORS Access-Control-Allow-Headers est ignoré?


119

J'ai du mal à faire fonctionner correctement une requête CORS interdomaine avec Chrome.

En-têtes de demande:

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4

En-têtes de réponse:

Access-Control-Allow-Headers:*
Access-Control-Allow-Origin:*
Allow:GET, POST, OPTIONS
Content-Length:0
Date:Tue, 30 Oct 2012 20:04:28 GMT
Server:BaseHTTP/0.3 Python/2.7.3

Erreur:

XMLHttpRequest cannot load domain. Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

Et le code python servant la demande d'options est:

self.send_response(200)
self.send_header('Allow', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Headers', '*')
self.send_header('Content-Length', '0')
self.end_headers()

Il semble que le Access-Control-Allow-Originjoker est ignoré?

Réponses:


186

La prise en charge des caractères génériques dans l'en- Access-Control-Allow-Headerstête n'a été ajoutée au niveau de vie qu'en mai 2016, elle peut donc ne pas être prise en charge par tous les navigateurs. Sur un navigateur qui ne l'implémente pas encore, il doit s'agir d'une correspondance exacte: https://www.w3.org/TR/2014/REC-cors-20140116/#access-control-allow-headers-response-header

Si vous attendez un grand nombre d'en-têtes, vous pouvez lire la valeur de l'en- Access-Control-Request-Headerstête et renvoyer cette valeur dans l'en- Access-Control-Allow-Headerstête.


55
resp.setHeader ("Access-Control-Allow-Headers", req.getHeader ("Access-Control-Request-Headers")); // autoriser tous les en
Sam Barnum

3
Sur ruby, «if request.headers ['Access-Control-Request-Headers'] then headers ['Access-Control-Allow-Headers'] = request.headers ['Access-Control-Request-Headers'] end» semble OK pour moi.
Tsuneo Yoshioka

1
@monsur: cette réponse a souligné que les caractères génériques sont autorisés maintenant, du moins en théorie, j'ai donc mis à jour votre réponse pour refléter cela. Si vous n'aimez pas mon style, n'hésitez pas à modifier à votre goût.
MvG

2
Un mot d'avertissement, vous pouvez rencontrer des problèmes en vous appuyant sur le renvoi de la valeur Access-Control-Request-Headers si vous autorisez également le navigateur à mettre en cache la réponse de contrôle en amont (avec Access-Control-Max-Age). Vous ne savez pas que la première requête répertorie tous les en-têtes de requêtes consécutives.
Simon Ejsing

2
@monokrome serait formidable si vous pouviez nous dire en quoi cela poserait un problème de sécurité en production ..
prettyvoid

53

Ces en-têtes CORS ne prennent pas en charge en *tant que valeur, le seul moyen est de les remplacer *par ceci:

Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With


.htaccess Exemple (CORS inclus):

<IfModule mod_headers.c>
  Header unset Connection
  Header unset Time-Zone
  Header unset Keep-Alive
  Header unset Access-Control-Allow-Origin
  Header unset Access-Control-Allow-Headers
  Header unset Access-Control-Expose-Headers
  Header unset Access-Control-Allow-Methods
  Header unset Access-Control-Allow-Credentials

  Header set   Connection                         keep-alive
  Header set   Time-Zone                          "Asia/Jerusalem"
  Header set   Keep-Alive                         timeout=100,max=500
  Header set   Access-Control-Allow-Origin        "*"
  Header set   Access-Control-Allow-Headers       "Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With"
  Header set   Access-Control-Expose-Headers      "Accept, Accept-CH, Accept-Charset, Accept-Datetime, Accept-Encoding, Accept-Ext, Accept-Features, Accept-Language, Accept-Params, Accept-Ranges, Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Request-Headers, Access-Control-Request-Method, Age, Allow, Alternates, Authentication-Info, Authorization, C-Ext, C-Man, C-Opt, C-PEP, C-PEP-Info, CONNECT, Cache-Control, Compliance, Connection, Content-Base, Content-Disposition, Content-Encoding, Content-ID, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Script-Type, Content-Security-Policy, Content-Style-Type, Content-Transfer-Encoding, Content-Type, Content-Version, Cookie, Cost, DAV, DELETE, DNT, DPR, Date, Default-Style, Delta-Base, Depth, Derived-From, Destination, Differential-ID, Digest, ETag, Expect, Expires, Ext, From, GET, GetProfile, HEAD, HTTP-date, Host, IM, If, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Keep-Alive, Label, Last-Event-ID, Last-Modified, Link, Location, Lock-Token, MIME-Version, Man, Max-Forwards, Media-Range, Message-ID, Meter, Negotiate, Non-Compliance, OPTION, OPTIONS, OWS, Opt, Optional, Ordering-Type, Origin, Overwrite, P3P, PEP, PICS-Label, POST, PUT, Pep-Info, Permanent, Position, Pragma, ProfileObject, Protocol, Protocol-Query, Protocol-Request, Proxy-Authenticate, Proxy-Authentication-Info, Proxy-Authorization, Proxy-Features, Proxy-Instruction, Public, RWS, Range, Referer, Refresh, Resolution-Hint, Resolver-Location, Retry-After, Safe, Sec-Websocket-Extensions, Sec-Websocket-Key, Sec-Websocket-Origin, Sec-Websocket-Protocol, Sec-Websocket-Version, Security-Scheme, Server, Set-Cookie, Set-Cookie2, SetProfile, SoapAction, Status, Status-URI, Strict-Transport-Security, SubOK, Subst, Surrogate-Capability, Surrogate-Control, TCN, TE, TRACE, Timeout, Title, Trailer, Transfer-Encoding, UA-Color, UA-Media, UA-Pixels, UA-Resolution, UA-Windowpixels, URI, Upgrade, User-Agent, Variant-Vary, Vary, Version, Via, Viewport-Width, WWW-Authenticate, Want-Digest, Warning, Width, X-Content-Duration, X-Content-Security-Policy, X-Content-Type-Options, X-CustomHeader, X-DNSPrefetch-Control, X-Forwarded-For, X-Forwarded-Port, X-Forwarded-Proto, X-Frame-Options, X-Modified, X-OTHER, X-PING, X-PINGOTHER, X-Powered-By, X-Requested-With"
  Header set   Access-Control-Allow-Methods       "CONNECT, DEBUG, DELETE, DONE, GET, HEAD, HTTP, HTTP/0.9, HTTP/1.0, HTTP/1.1, HTTP/2, OPTIONS, ORIGIN, ORIGINS, PATCH, POST, PUT, QUIC, REST, SESSION, SHOULD, SPDY, TRACE, TRACK"
  Header set   Access-Control-Allow-Credentials   "true"

  Header set DNT "0"
  Header set Accept-Ranges "bytes"
  Header set Vary "Accept-Encoding"
  Header set X-UA-Compatible "IE=edge,chrome=1"
  Header set X-Frame-Options "SAMEORIGIN"
  Header set X-Content-Type-Options "nosniff"
  Header set X-Xss-Protection "1; mode=block"
</IfModule>

FAQ:

  • Pourquoi Access-Control-Allow-Headers, Access-Control-Expose-Headers, les Access-Control-Allow-Methodsvaleurs sont super long?

    Ceux-ci ne prennent pas en charge la *syntaxe, j'ai donc rassemblé les en-têtes les plus courants (et exotiques) du Web, dans divers formats # 1 # 2 # 3 (et je mettrai à jour la liste de temps en temps)

  • Pourquoi utilisez-vous la Header unset ______syntaxe?

    Les serveurs GoDaddy (sur lesquels mon site Web est hébergé ..) ont un bogue étrange où si les en-têtes sont déjà définis, la valeur précédente rejoindra celle existante .. (au lieu de la remplacer) de cette façon, je "pré-nettoie" les valeurs existantes (vraiment juste une solution rapide et sale )

  • Puis-je utiliser «tel quel» en toute sécurité?

    Eh bien ... la plupart du temps, la réponse serait OUI puisque la .htaccesslimite les en-têtes aux scripts (PHP, HTML, ...) et aux ressources (.JPG, .JS, .CSS) servis à partir de l'emplacement de "dossier" suivant. Vous pouvez éventuellement supprimer les Access-Control-Allow-Methodslignes. En outre Connection, Time-Zone, Keep-Aliveet DNT, Accept-Ranges, Vary, X-UA-Compatible, X-Frame-Options, X-Content-Type-Optionset X-Xss-Protectionsont juste une suggestion que je utilise pour mon service en ligne .. vous pouvez retirer ceux qui sont trop ...

tiré de mon commentaire ci-dessus


Cela m'a définitivement sauvé la vie. J'utilisais un fournisseur CDN, avec CORS activé, et je l'autorisais également dans mon site Web avec Access-Control-Allow-Origin "*"mais rien ne fonctionnait jusqu'à ce que je l'utilise. Même le fournisseur de CDN n'avait pas de réponse pour nous. Je dirige le site Web dans Siteground , peut-être, en tant que GoDaddy , il est obligatoire de tout débloquer d'abord.
Ignacio Bustos

Excellent post, cela devrait être remonté en haut de cette page.
CommonKnowledge

1
Dans mon cas particulier, j'ai dû supprimer de Access-Control-Allow-Methodstoutes ces méthodes: HTTP / 0.9, HTTP / 1.0, HTTP / 1.1, HTTP / 2
umbe1987

HTTP / 2 est-il même une «méthode» valide? La mise à niveau de HTTP / 1.1 vers 2 fonctionne-t-elle comme ça ou quelque chose comme ça? Si je regarde ici: sookocheff.com/post/networking/how-does-http-2-work, la partie HTTP / ... est censée aller comme troisième endroit, pas le premier, où la méthode est placée.
Henk Poley le

Peut-être que pour prendre en charge HTTP / 2.0, vous devez ajouter la méthode 'PRI'?
Henk Poley le

17

J'ai trouvé que cela Access-Control-Allow-Headers: *devrait être défini UNIQUEMENT pour la demande OPTIONS. Si vous le renvoyez pour une demande POST, le navigateur annule la demande (au moins pour Chrome)

Le code PHP suivant fonctionne pour moi

// Allow CORS
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_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 des réponses trompeuses:

  • Le thread du serveur dit qu'il s'agit d'un bogue de chrome de 2 ans: Access-Control-Allow-Headersne correspond pas à localhost. C'est faux: je peux utiliser CORS sur mon serveur local avec Post normalement
  • Access-Control-Allow-Headersaccepte 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 résoudre le problème.

Bon codage


2
Wildcard ("Access-Control-Allow-Headers: *") ne fonctionnait pas pour moi, sur Safari 7.0.4.
Tsuneo Yoshioka

J'ai trouvé que le paramètre Access-Control-Allow-Headers fonctionne pour POST dans Chrome Version 40.0.2214.111 m.
Derek Greer

3
Cela ne semble pas juste ..... La spécification ne permet pas *le Access-Control-Allow-Headersmême OPTIONS.
Pacerier

1

Cité de Monsur,

L'en-tête Access-Control-Allow-Headers n'autorise pas les caractères génériques. Il doit s'agir d'une correspondance exacte: http://www.w3.org/TR/cors/#access-control-allow-headers-response-header .

Voici donc ma solution php.

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  $headers=getallheaders();
  @$ACRH=$headers["Access-Control-Request-Headers"];
  header("Access-Control-Allow-Headers: $ACRH");
}

1
En fait, pourquoi pas simplementheader('Access-Control-Allow-Headers: ' . $_SERVER['HTTP_ACCESS_CONTROL_ALLOW_HEADERS']);
Pacerier

0

voici l'incantation pour nginx, à l'intérieur d'un

location / {
    # Simple requests
    if ($request_method ~* "(GET|POST)") {
      add_header "Access-Control-Allow-Origin"  *;
    }

    # Preflighted requests
    if ($request_method = OPTIONS ) {
      add_header "Access-Control-Allow-Origin"  *;
      add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
      add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
    }

}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.