CORS访问控制允许头信息通配符被忽略了吗?

134

我在使用Chrome时遇到了跨域CORS请求无法正常工作的问题。

请求头:

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

响应头:

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

错误:

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

Python代码用于处理选项请求如下:

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()
似乎 Access-Control-Allow-Origin 通配符被忽略了?
6个回答

193
支持在 Access-Control-Allow-Headers 头部使用通配符的功能直到 2016 年 5 月才被加入到标准规范中(参考链接),因此并非所有浏览器都支持该功能。在尚未实现该功能的浏览器上,必须完全匹配: https://www.w3.org/TR/2014/REC-cors-20140116/#access-control-allow-headers-response-header 如果您预计要传输大量头信息,您可以读取 Access-Control-Request-Headers 头信息的值,并将该值回显到 Access-Control-Allow-Headers 头信息中。

56
resp.setHeader("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers")); // 允许任何请求头 - Sam Barnum
3
在 Ruby 中,"if request.headers['Access-Control-Request-Headers'] then headers['Access-Control-Allow-Headers'] = request.headers['Access-Control-Request-Headers'] end" 看起来对我来说没问题。 - Tsuneo Yoshioka
1
@monsur:这个答案指出现在通配符是被允许的,至少在理论上是这样的,所以我更新了你的答案来反映这一点。如果你不喜欢我的风格,可以随意编辑成你喜欢的样式。 - MvG
3
警告:如果您依赖于返回 Access-Control-Request-Headers 值并允许浏览器缓存预检请求响应(使用 Access-Control-Max-Age),则可能会遇到问题。您不知道第一个请求列出了所有连续请求的标头。 - Simon Ejsing
4
@monokrome 如果您能告诉我们在生产中这将如何成为安全问题,那将非常好。 - prettyvoid
显示剩余4条评论

60
那些CORS标头不支持*作为值,唯一的方法是用这个替换: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示例(包括CORS):

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

常见问题解答:

  • 为什么Access-Control-Allow-HeadersAccess-Control-Expose-HeadersAccess-Control-Allow-Methods的值这么长?

    这些不支持*语法,因此我从网上收集了最常见(和奇特)的头文件,并以各种格式进行整理#1 #2 #3(我会定期更新列表)

  • 为什么要使用Header unset ______语法?

    GoDaddy服务器(我的网站托管在其中..)有一个奇怪的错误,即如果已经设置了头,则先前的值将与现有的值连接在一起。(而不是替换它),这样我就可以“预清除”现有的值。(实际上只是一个快速&脏的解决方案)

  • 我可以直接使用吗?

    嗯..大多数情况下答案是,因为.htaccess限制了这些头文件仅可供来自以下“文件夹”-位置的脚本(PHP,HTML,...)和资源(.JPG,.JS,.CSS)使用。您可以选择删除Access-Control-Allow-Methods行。 此外,ConnectionTime-ZoneKeep-AliveDNTAccept-RangesVaryX-UA-CompatibleX-Frame-OptionsX-Content-Type-OptionsX-Xss-Protection只是我正在使用的在线服务的建议..随意删除这些...

摘自我的上面的评论


这绝对救了我的命。我使用了一个启用了CORS的CDN提供商,并且在我的网站上允许了它,使用 Access-Control-Allow-Origin "*",但是直到我使用了这个东西,什么都没有起作用。甚至CDN提供商也无法为我们提供答案。我在 Siteground 上运行网站,也许像 GoDaddy 这样的平台,必须首先取消所有设置。 - Ignacio Bustos
1
在我的特定情况下,我必须从“Access-Control-Allow-Methods”中删除所有这些方法:HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2。 - umbe1987
HTTP/2是一种有效的“方法”吗?从HTTP/1.1升级到2是否像那样工作?如果我在这里看:https://sookocheff.com/post/networking/how-does-http-2-work/,HTTP/...部分应该放在第三个位置,而不是放在方法所在的第一个位置。 - Henk Poley
也许要支持HTTP/2.0,你需要添加'PRI'方法? - Henk Poley
顺便提一句,我注意到safari不允许使用Access-Control-Allow-Origin: '*' - Henk Poley
ASP.NET和SignalR用户需要将x-signalr-user-agent添加到列表中。 - Qwertie

17

我发现Access-Control-Allow-Headers: *应该仅用于OPTIONS请求。如果你为POST请求返回它,那么浏览器会取消请求(至少对于Chrome)。

以下PHP代码适用于我:

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

我发现有一些误导性的回答跟这个问题很相似:

  • 服务器线程说这是Chrome的一个2年老Bug:Access-Control-Allow-Headers不与本地主机匹配。但这是错误的:我可以使用CORS来正常地将Post请求发送到我的本地服务器。
  • Access-Control-Allow-Headers确实接受通配符,所以这也是错误的,通配符在我的情况下有效(我只测试了Chrome)。

这让我花了半天时间才找到问题所在。

祝编码愉快。


2
通配符(“Access-Control-Allow-Headers:*”)在Safari 7.0.4上对我不起作用。 - Tsuneo Yoshioka
我发现在Chrome版本40.0.2214.111 m中设置Access-Control-Allow-Headers对于POST请求有效。 - Derek Greer
4
这看起来不太对劲……规范不允许在Access-Control-Allow-Headers中使用*,即使是针对OPTIONS请求也不行。 - Pacerier

2
我被绊倒了,因为我实际想要的是一个稍微不同的页眉。
  • access-control-ALLOW-headers 只适用于预检请求。MDN文档
  • access-control-EXPOSE-headers 适用于请求本身,意味着JavaScript可以读取在此声明的头信息。这就是我需要的。MDN文档
我知道这与主题有些关系,但我希望这能帮助到某个人。

1

2
其实,为什么不直接使用 header('Access-Control-Allow-Headers: ' . $_SERVER['HTTP_ACCESS_CONTROL_ALLOW_HEADERS']); 呢? - Pacerier
感谢您的建议。我已经更新了我的答案。 - Jason Chiang

1
这是关于nginx的咒语,在一个

标签内。
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";
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接