O curinga CORS Access-Control-Allow-Headers está sendo ignorado?

118

Estou tendo problemas para fazer com que uma solicitação CORS entre domínios funcione corretamente usando o Chrome.

Solicitar cabeçalhos:

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

Cabeçalhos de resposta:

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

Erro:

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

E o código Python que atende à solicitação de opções é:

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()

Parece que o Access-Control-Allow-Origincuringa está sendo ignorado?

Ben Reeves
fonte

Respostas:

185

O suporte para curingas no Access-Control-Allow-Headerscabeçalho foi adicionado ao padrão de vida apenas em maio de 2016, portanto, pode não ser compatível com todos os navegadores. Em navegadores que ainda não implementam isso, deve ser uma correspondência exata: https://www.w3.org/TR/2014/REC-cors-20140116/#access-control-allow-headers-response-header

Se você espera um grande número de cabeçalhos, pode ler o valor do Access-Control-Request-Headerscabeçalho e repetir esse valor no Access-Control-Allow-Headerscabeçalho.

monsur
fonte
55
resp.setHeader ("Access-Control-Allow-Headers", req.getHeader ("Access-Control-Request-Headers")); // permitir qualquer cabeçalho
Sam Barnum
3
No ruby, "if request.headers ['Access-Control-Request-Headers'] then headers ['Access-Control-Allow-Headers'] = request.headers ['Access-Control-Request-Headers'] end" parece Tudo bem, por mim.
Tsuneo Yoshioka
1
@monsur: esta resposta apontou que curingas são permitidos agora, pelo menos em teoria, então eu atualizei sua resposta para refletir isso. Se você não gosta do meu estilo, fique à vontade para editar a seu gosto.
MvG
2
Uma palavra de advertência: você pode ter problemas ao contar com a devolução do valor Access-Control-Request-Headers se também permitir que o navegador armazene em cache a resposta de comprovação (com Access-Control-Max-Age). Você não sabe que a primeira solicitação lista todos os cabeçalhos de solicitações consecutivas.
Simon Ejsing
2
O @monokrome seria ótimo se você pudesse nos dizer como isso seria uma preocupação de segurança na produção ..
prettyvoid
52

Esses cabeçalhos CORS não suportam *como valor, a única maneira é substituí-los *por:

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 Exemplo (CORS incluído):

<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>

PERGUNTAS FREQUENTES:

  • Por que Access-Control-Allow-Headers, Access-Control-Expose-Headers, Access-Control-Allow-Methodsvalores são super longa?

    Eles não suportam a *sintaxe, então eu coletei os cabeçalhos mais comuns (e exóticos) de toda a web, em vários formatos # 1 # 2 # 3 (e irei atualizar a lista de tempos em tempos)

  • Por que você usa Header unset ______sintaxe?

    Os servidores GoDaddy (nos quais meu site está hospedado ..) têm um bug estranho onde se os cabeçalhos já estiverem configurados, o valor anterior irá se juntar ao existente .. (em vez de substituí-lo) desta forma eu "pré-limpo" os valores existentes (na verdade apenas uma solução rápida e suja )

  • É seguro usar "no estado em que se encontra"?

    Bem ... principalmente a resposta seria SIM, pois .htaccessestá limitando os cabeçalhos aos scripts (PHP, HTML, ...) e recursos (.JPG, .JS, .CSS) servidos a partir da seguinte "pasta" -local. Opcionalmente, você pode querer remover as Access-Control-Allow-Methodslinhas. Além disso Connection, Time-Zone, Keep-Alivee DNT, Accept-Ranges, Vary, X-UA-Compatible, X-Frame-Options, X-Content-Type-Optionse X-Xss-Protectionsão apenas uma sugestão que eu estou usando para o meu serviço online .. sinta-se livre para remover os demais ...

tirado do meu comentário acima

Comunidade
fonte
Isso definitivamente salvou minha vida. Eu estava usando um provedor CDN, com CORS habilitado, e também estava permitindo no meu site com Access-Control-Allow-Origin "*"mas nada funcionou até que usei isso. Nem mesmo o provedor de CDN tinha uma resposta para nós. Eu corro o site em Siteground , talvez, como GoDaddy , seja obrigatório desmarcar primeiro tudo.
Ignacio Bustos
Excelente postagem, isso deve ser colocado no topo desta página.
CommonKnowledge
1
No meu caso específico, tive que remover Access-Control-Allow-Methodstodos estes métodos: HTTP / 0.9, HTTP / 1.0, HTTP / 1.1, HTTP / 2
umbe1987
O HTTP / 2 é mesmo um 'Método' válido? A atualização de HTTP / 1.1 para 2 funciona assim ou algo assim? Se eu olhar aqui: sookocheff.com/post/networking/how-does-http-2-work, a parte HTTP / ... deve ir como o terceiro lugar, não o primeiro, onde o Método é colocado.
Henk Poley
Talvez para suportar HTTP / 2.0 você precise adicionar o método 'PRI'?
Henk Poley
17

Achei que Access-Control-Allow-Headers: *deveria ser definido SOMENTE para a solicitação de OPÇÕES. Se você devolvê-lo para a solicitação POST, o navegador cancela a solicitação (pelo menos para o Chrome)

O seguinte código PHP funciona para mim

// 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: *");
}

Encontrei perguntas semelhantes com algumas respostas enganosas:

  • A thread do servidor diz que este é um bug de 2 anos do cromo: Access-Control-Allow-Headersnão corresponde ao localhost. Está errado: posso usar CORS para meu servidor local com Post normalmente
  • Access-Control-Allow-Headersaceita curingas. Também está errado, curinga funciona para mim (eu testei apenas com o Chrome)

Isso me leva meio dia para descobrir o problema.

Boa codificação

verde
fonte
2
O curinga ("Access-Control-Allow-Headers: *") não funcionou para mim, no Safari 7.0.4.
Tsuneo Yoshioka
Descobri que a configuração de Access-Control-Allow-Headers funciona para POST na versão do Chrome 40.0.2214.111 m.
Derek Greer em
3
Isso não parece certo ..... A especificação não permite *no Access-Control-Allow-Headersmesmo para OPTIONS.
Pacerier
1

Citado de Monsur,

O cabeçalho Access-Control-Allow-Headers não permite curingas. Deve ser uma correspondência exata: http://www.w3.org/TR/cors/#access-control-allow-headers-response-header .

Então aqui está minha solução de php.

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
  $headers=getallheaders();
  @$ACRH=$headers["Access-Control-Request-Headers"];
  header("Access-Control-Allow-Headers: $ACRH");
}
Jason Chiang
fonte
1
Na verdade, por que não simplesmenteheader('Access-Control-Allow-Headers: ' . $_SERVER['HTTP_ACCESS_CONTROL_ALLOW_HEADERS']);
Pacerier
0

aqui está o encantamento para nginx, dentro de um

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";
    }

}
dcsan
fonte