获取API;如果响应是不透明的,为什么要使用 "no-cors" 模式?
Fetch API; why use the "no-cors" mode if the response is Opaque?
我读了 and this question。前者只解释'no-cors' vs 'same-origin';后者建议 'no-cors' 没有用,因为不透明响应(Javascript 不能 read/do 任何有用的东西):
You basically never ever want to use mode: 'no-cors' in practice —
except in some very limited cases. That’s because what setting mode:
'no-cors' actually says to the browser is, “Block my frontend
JavaScript code from looking into the contents of the response body
and headers under all circumstances.” In most cases that’s obviously
really not what you want.
有人可以建议 这些 "limited cases" 的示例是什么我们想在其中使用 "no-cors"(即使响应是不透明的?)
我能想到的唯一情况是一种单向通信;如果客户端向服务器发送 GET 或 POST 就足够了, 只需让服务器可以跟踪请求的发生; (例如,增加请求计数器); ...
...那么响应是一个 OpaqueResponse 就足够了;即客户端只需要知道请求是否成功(状态 200),不需要任何负载响应。
我的想法是一个有效的例子吗?有人可以推荐 'no-cors' 用法的其他可能性/用例/示例吗?
请记住,CORS 设置不会阻止请求到达服务器 - 这就是身份验证和 CSRF 的用途。相反,它会阻止页面读取响应。请求仍然是:
- 从页面发送,
- 浏览器添加
Origin
header,
- 它仍然由服务器处理(通常 - CORS 与此无关,尽管可能有其他安全措施),
- 当返回时,浏览器检查 header 对
Access-Control-Allow-Origin
的响应。如果它与浏览器认为的 Origin
相匹配,那么浏览器会让页面看到请求的结果。
这是关键 - Same-origin 策略和 CORS 设置不允许协作浏览器中的页面看到响应。
请注意上面还有一个步骤 0,这是一个选项 "pre-flight check" 被发送来检查如果请求通过,是否允许页面看到结果?如果不是,那么他们认为发送请求没有什么意义 - 但这是一个假设。
现在回答这个问题
mode: no-cors
做了两件事:
- 说不需要看结果
- 所以它不会发送 pre-flight 检查
在我的脑海中,这就是我认为我可以用它来做什么(其中一些是邪恶的)
- 任何时候我不需要看到响应,例如日志记录、跟踪或黑客攻击;当前端代码本质上是
try { const notNeeded = fetch(...) } catch { console.log('Tough luck, do nothing') }
- 任何时候我想通过不发送预检检查来尽快将数据发送到服务器。当我真的需要数据时,我总是可以稍后发送带有 CORS 的 GET 来读取数据。
- Caching, detailed in this answer
提醒
CORS 执行上述操作。它不执行以下操作:
- 阻止服务器处理请求 - 这就是身份验证和 CSRF 预防的目的。
- 停止欺骗 Origin header - 这仅适用于协作浏览器。作为攻击者,您通常无权访问用户使用的浏览器。因为 header 可以被欺骗,服务器不应该使用其中的数据来保证安全。 (这就是为什么在通过 CURL/Postman/Insomnia 之类的工具测试浏览器 API 时,您需要检查 CORS header 是否通过,因为它们接受所有响应并且永远不会应用 CORS 策略。)
no-cors
模式限制了获取 API 的操作,就像使用 form
元素可能(并且一直是)可能的那样,加上一些“小”额外功能 —执行 MDN 文档称为 "simple" 的一种请求。此外,就像表单一样,无法访问响应。
表单(以及所有其他 HTML 元素)可以在不使用 CORS 协议的情况下执行 cross-site 请求——它们的存在和行为早于 CORS 协议。
额外的能力是那些超出HTML元素所能达到的简单请求:使用HEAD
方法,改变简单的值headers, set/change parameters 的简单内容类型,例如 charset
.
我相信 no-cors
模式的存在是为了支持 HTML 元素提出的请求的实现。 mode
的 MDN 文档中的这个声明似乎证实了这个想法:
However, for requests created other than by the Request() constructor, no-cors
is typically used as the mode
; for example, for embedded resources where the request is initiated from markup, unless the crossorigin
attribute is present, the request is in most cases made using the no-cors
mode — that is, for the <link>
or <script>
elements (except when used with modules), or <img>
, <audio>
, <video>
, <object>
, <embed>
, or <iframe>
elements.
除此之外,我能想到的所有 cross-site 用例都可以改用 cors
模式,提供更多功能(复杂请求),而不会损失安全性。
关于请求 simplicity/complexity 的注释。在 fetch/CORS 规范中,相同的请求类型概念称为 CORS“安全”,其中 safety 指的是 safe for old servers in face the new“ XHR/fetch 引入的“不安全”请求类型。然而,简单的请求本身绝不能被认为是普遍安全的。事实上,正是这些相同的请求类型在导致 server-side 持久状态突变时,必须防止 CSRF 攻击!我想这就是 MDN 将它们重新命名为“简单”(但通常不安全!)的原因。作为参考,fetch/CORS 规范提到 CORS-safety 关于 methods, headers,后者包括特殊的 Content-Type
header,等等。
我读了
You basically never ever want to use mode: 'no-cors' in practice — except in some very limited cases. That’s because what setting mode: 'no-cors' actually says to the browser is, “Block my frontend JavaScript code from looking into the contents of the response body and headers under all circumstances.” In most cases that’s obviously really not what you want.
有人可以建议 这些 "limited cases" 的示例是什么我们想在其中使用 "no-cors"(即使响应是不透明的?)
我能想到的唯一情况是一种单向通信;如果客户端向服务器发送 GET 或 POST 就足够了, 只需让服务器可以跟踪请求的发生; (例如,增加请求计数器); ...
...那么响应是一个 OpaqueResponse 就足够了;即客户端只需要知道请求是否成功(状态 200),不需要任何负载响应。
我的想法是一个有效的例子吗?有人可以推荐 'no-cors' 用法的其他可能性/用例/示例吗?
请记住,CORS 设置不会阻止请求到达服务器 - 这就是身份验证和 CSRF 的用途。相反,它会阻止页面读取响应。请求仍然是:
- 从页面发送,
- 浏览器添加
Origin
header, - 它仍然由服务器处理(通常 - CORS 与此无关,尽管可能有其他安全措施),
- 当返回时,浏览器检查 header 对
Access-Control-Allow-Origin
的响应。如果它与浏览器认为的Origin
相匹配,那么浏览器会让页面看到请求的结果。
这是关键 - Same-origin 策略和 CORS 设置不允许协作浏览器中的页面看到响应。
请注意上面还有一个步骤 0,这是一个选项 "pre-flight check" 被发送来检查如果请求通过,是否允许页面看到结果?如果不是,那么他们认为发送请求没有什么意义 - 但这是一个假设。
现在回答这个问题
mode: no-cors
做了两件事:
- 说不需要看结果
- 所以它不会发送 pre-flight 检查
在我的脑海中,这就是我认为我可以用它来做什么(其中一些是邪恶的)
- 任何时候我不需要看到响应,例如日志记录、跟踪或黑客攻击;当前端代码本质上是
try { const notNeeded = fetch(...) } catch { console.log('Tough luck, do nothing') }
- 任何时候我想通过不发送预检检查来尽快将数据发送到服务器。当我真的需要数据时,我总是可以稍后发送带有 CORS 的 GET 来读取数据。
- Caching, detailed in this answer
提醒
CORS 执行上述操作。它不执行以下操作:
- 阻止服务器处理请求 - 这就是身份验证和 CSRF 预防的目的。
- 停止欺骗 Origin header - 这仅适用于协作浏览器。作为攻击者,您通常无权访问用户使用的浏览器。因为 header 可以被欺骗,服务器不应该使用其中的数据来保证安全。 (这就是为什么在通过 CURL/Postman/Insomnia 之类的工具测试浏览器 API 时,您需要检查 CORS header 是否通过,因为它们接受所有响应并且永远不会应用 CORS 策略。)
no-cors
模式限制了获取 API 的操作,就像使用 form
元素可能(并且一直是)可能的那样,加上一些“小”额外功能 —执行 MDN 文档称为 "simple" 的一种请求。此外,就像表单一样,无法访问响应。
表单(以及所有其他 HTML 元素)可以在不使用 CORS 协议的情况下执行 cross-site 请求——它们的存在和行为早于 CORS 协议。
额外的能力是那些超出HTML元素所能达到的简单请求:使用HEAD
方法,改变简单的值headers, set/change parameters 的简单内容类型,例如 charset
.
我相信 no-cors
模式的存在是为了支持 HTML 元素提出的请求的实现。 mode
的 MDN 文档中的这个声明似乎证实了这个想法:
However, for requests created other than by the Request() constructor,
no-cors
is typically used as themode
; for example, for embedded resources where the request is initiated from markup, unless thecrossorigin
attribute is present, the request is in most cases made using theno-cors
mode — that is, for the<link>
or<script>
elements (except when used with modules), or<img>
,<audio>
,<video>
,<object>
,<embed>
, or<iframe>
elements.
除此之外,我能想到的所有 cross-site 用例都可以改用 cors
模式,提供更多功能(复杂请求),而不会损失安全性。
关于请求 simplicity/complexity 的注释。在 fetch/CORS 规范中,相同的请求类型概念称为 CORS“安全”,其中 safety 指的是 safe for old servers in face the new“ XHR/fetch 引入的“不安全”请求类型。然而,简单的请求本身绝不能被认为是普遍安全的。事实上,正是这些相同的请求类型在导致 server-side 持久状态突变时,必须防止 CSRF 攻击!我想这就是 MDN 将它们重新命名为“简单”(但通常不安全!)的原因。作为参考,fetch/CORS 规范提到 CORS-safety 关于 methods, headers,后者包括特殊的 Content-Type
header,等等。