我啥时候应该在我的响应标头中真正将“Access-Control-Allow-Credentials”设置为“true”?

Posted

技术标签:

【中文标题】我啥时候应该在我的响应标头中真正将“Access-Control-Allow-Credentials”设置为“true”?【英文标题】:When should I really set "Access-Control-Allow-Credentials" to "true" in my response headers?我什么时候应该在我的响应标头中真正将“Access-Control-Allow-Credentials”设置为“true”? 【发布时间】:2017-12-13 17:36:53 【问题描述】:

MDN 表示,当必须在站点之间交换 cookie、授权标头或 TLS 客户端证书等凭据时,Access-Control-Allow-Crendentials 必须设置为 true

考虑两个站点 A - https://example1.xyz.com,另一个是 B- https://example2.xyz.com。现在我必须从 A 向 B 发出 http Get 请求。当我从 A 请求 B 时,我得到了,

“请求中没有“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://example1.xyz.com” 访问。”

所以,我在 B 中添加以下响应标头

response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));

这解决了同源错误,我可以向 B 请求。我应该何时以及为什么要设置

response.setHeader("Access-Control-Allow-Credentials", "true");

当我用谷歌搜索解决这个same-origin 错误时,他们中的大多数人建议同时使用这两个标题。我不清楚使用第二个Access-Control-Allow-Credentials

    什么时候应该同时使用这两种方法? 为什么要将Access-Control-Allow-Origin设置为从请求头获取的origin而不是通配符*

请给我举个例子更好地理解它。

【问题讨论】:

【参考方案1】:

如果您希望请求也能够发送 cookie,则需要允许凭据。如果您需要授权传入请求,基于会话 ID cookie 将是一个常见原因。

设置通配符允许任何站点向您的端点发出请求。如果请求与您定义的白名单匹配,则设置允许来源很常见。一些浏览器会缓存允许响应,如果您也从另一个域请求相同的内容,这可能会导致请求被拒绝。

【讨论】:

解释得很清楚@clint...Some browsers will cache the allow response 的意思是-当浏览器再次请求时-不会从浏览器发送预检请求对吗?它会直接得到跳过初始请求的响应吗?我是否以正确的方式理解它? 非常感谢 - 如果 OPTIONS 请求被缓存,它将不会被发送。您可以设置一个查询字符串参数来对主机名进行版本控制,?hostname=... 或者一种常见的做法是当前的 unix 时间戳。那是假设您要发回一个明确允许的来源。 我无法将您带到这里@clint.. 当我从同一个域访问时,我已经看到在请求中使用时间戳 - 当我像 https://example1.xyz.com?fileid=123 这样请求时 - 浏览器会缓存它的回应。因此,当我从客户端调用相同的请求时 - 响应将从浏览器缓存中获取,而不是发送到服务器。因此,我们会将时间戳附加到请求中,例如 https://example1.xyz.com?fileid=123&&_t=123456 - 我们将添加请求以将其标识为唯一请求 即;说浏览器它与您之前调用的浏览器不同 - 因此,请求将被发送到服务器而不是从浏览器缓存中获取它.. 但是我不确定这个“OPTIONS”请求会在这里缓存什么信息.....我不清楚这个@clint That is assuming you are sending back a specifically allowed origin - 请再解释一下..【参考方案2】:

设置Access-Control-Allow-Credentials: true其实有两个作用:

如果包含凭据,则会导致浏览器 to actually allow your frontend javascript code to access the response 导致任何 Set-Cookie 响应标头 to actually have the effect of setting a cookie(否则将忽略 Set-Cookie 响应标头)

这些效果与设置 XMLHttpRequest.withCredentialscredentials: 'include' (Fetch API) 的效果相结合,导致 credentials (HTTP cookies, TLS client certificates, and authentication entries) 实际上被包含在请求中。

Fetch 规范中的https://fetch.spec.whatwg.org/#example-cors-with-credentials 有一个很好的例子

【讨论】:

TLS/SSL 客户端证书是一种旧的、很少使用的机制,旨在提供完全无密码登录和一种双因素身份验证。在blog.pilif.me/2008/05/26/… 有很好但很老的文章,在news.ycombinator.com/item?id=6026102 有相关的更新讨论【参考方案3】:

为什么要将Access-Control-Allow-Origin设置为从请求头获取的origin而不是通配符*

除非你非常确定你在做什么,否则你不应该这样做。

以下情况实际上是安全的:

    您以这种方式设置响应标头的资源是旨在供所有人访问的公共站点或 API 端点,并且 您只是没有设置可能使攻击者能够访问敏感信息或机密数据的 cookie。

例如,如果您的服务器代码设置 cookie 只是为了保存应用程序状态或会话状态以方便您的用户,那么获取 Origin 请求标头的值并反映/是没有风险的在Access-Control-Allow-Origin 值中回显它,同时发送Access-Control-Allow-Credentials: true 响应标头。

另一方面,如果你设置的 cookie 暴露了敏感信息或机密数据,那么除非你真的确定你有其他东西被锁定(不知何故......)你真的想避免反映 Origin 回来在Access-Control-Allow-Origin 值中(无需在服务器端检查),同时还发送Access-Control-Allow-Credentials: true

如果您这样做,您可能会暴露敏感信息或机密数据,从而使恶意攻击者可以获取这些信息。有关风险的说明,请阅读以下内容:

https://web-in-security.blogspot.jp/2017/07/cors-misconfigurations-on-large-scale.html http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html

如果您发送 CORS 标头的资源不是一个旨在供所有人访问的公共站点或 API 端点,而是位于 Intranet 内或位于某个 IP 地址后面 -受限制的防火墙,那么您肯定真的想避免结合Access-Control-Allow-Origin-reflects-OriginAccess-Control-Allow-Credentials: true。 (在 Intranet 的情况下,您几乎总是希望只允许特定的硬编码/列入白名单的来源。)

【讨论】:

不包含Access-Control-Allow-Credentials也是安全的。这才是真正危险的标题。

以上是关于我啥时候应该在我的响应标头中真正将“Access-Control-Allow-Credentials”设置为“true”?的主要内容,如果未能解决你的问题,请参考以下文章

我啥时候应该使用助手? [关闭]

我啥时候应该使用“while 循环”?

带有正确标头的预检响应不成功

我啥时候应该使用“隐藏文本框”,啥时候应该使用(html 5)“数据属性”?

根据 CORS 预检响应中的标头“Access-Control-Allow-Headers”,标头“内容类型”是不允许的

我啥时候应该使用 mongoDB 而不是关系数据库