MDN说,当必须在站点之间交换cookie,授权标头或TLS客户端证书等凭据时,Access-Control-Allow-Crendentials
必须设置为true
。
考虑两个站点 A - https://example1.xyz.com,另一个是 B- https://example2.xyz.com。现在我必须发出从 A 到 B 的 httpGet
请求。当我从 A 请求 B 时,我得到,
"请求的上不存在'访问控制-允许源'标头 资源。因此不允许使用原产地"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
?
请引用我一个例子以更好地理解它。
如果您希望请求也能够发送cookie,则需要允许凭据。如果您需要授权传入的请求,基于会话 ID cookie 将是一个常见原因。
设置通配符允许任何站点向终结点发出请求。如果请求与您定义的白名单匹配,则通常允许源。某些浏览器会缓存 allow 响应,如果您也从另一个域请求相同的内容,这可能会导致请求被拒绝。
设置Access-Control-Allow-Credentials: true
实际上有两个效果:
- 导致浏览器实际上允许前端 JavaScript 代码访问响应(如果包含凭据(
- 使任何
Set-Cookie
响应标头实际上具有设置 cookie 的效果(否则将忽略Set-Cookie
响应标头(
这些影响与设置XMLHttpRequest.withCredentials
或credentials: 'include'
(提取 API( 导致凭据(HTTP Cookie、TLS 客户端证书和身份验证条目(实际包含在请求中的效果相结合。
https://fetch.spec.whatwg.org/#example-cors-with-credentials 有一个很好的例子。
为什么我应该将
Access-Control-Allow-Origin
设置为从请求标头而不是通配符*
获得origin
?
除非你非常确定自己在做什么,否则你不应该这样做。
在以下情况下,这样做实际上是安全的:
- 您以这种方式为其设置响应标头的资源是供所有人访问的公共站点或 API 终结点,并且
- 您只是没有设置可能使攻击者能够访问敏感信息或机密数据的 Cookie。
例如,如果您的服务器代码只是为了保存应用程序状态或会话状态以方便用户而设置 cookie,那么获取Origin
请求标头的值并将其反映/回显Access-Control-Allow-Origin
值,同时发送Access-Control-Allow-Credentials: true
响应标头,则没有风险。
另一方面,如果您设置的 cookie 暴露了敏感信息或机密数据,那么除非您真的确定您有其他锁定的东西(以某种方式......(,否则您真的希望避免在Access-Control-Allow-Origin
值中反映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
- 反射-Origin
和Access-Control-Allow-Credentials: true
结合起来。(在 Intranet 案例中,您几乎总是希望只允许特定的硬编码/白名单来源。