Fetch API; 如果响应是不透明的,为什么要使用“no-cors”模式?

12
我阅读了这篇问题这篇问题。前者仅解释了'no-cors'和'same-origin'的区别;后者建议不要使用'no-cors',因为响应不透明(Javascript无法读取或处理有用信息):
“实际上,在实践中基本上永远不需要使用mode: 'no-cors'——除非是一些非常有限的情况。这是因为设置mode: 'no-cors'实际上是告诉浏览器,“在任何情况下都要阻止我的前端JavaScript代码查看响应体和标头的内容。” 在大多数情况下,这显然不是您想要的。”
有人能指出这些“有限情况”的示例,我们何时需要使用“no-cors”(即使响应是Opaque)吗?
我唯一能想到的情况是一种单向通信;如果客户端只需向服务器发送GET或POST以便服务器跟踪请求发生的情况(例如增加请求计数器)...
...那么响应为OpaqueResponse就足够了;也就是说,客户端只需要知道请求是否成功(状态码200),不需要任何有效载荷响应。

我的想法是一个有效的例子吗?有人可以推荐其他可能性/用例/“no-cors”使用的例子吗?


2
请查看 https://dev59.com/3VkT5IYBdhLWcg3wELgl#39109790 的答案。主要情况是:(1) 当您想要做的唯一事情是缓存资源时,以及 (2) 当您想要将资源用作文档中 <script><link rel="stylesheet"><img><video><audio><object><embed><iframe> 元素的内容时(这是有效的,因为这些元素的跨域嵌入资源是允许的)。 - sideshowbarker
1
就缓存而言,如https://dev59.com/3VkT5IYBdhLWcg3wELgl#39109790所述,在实践中适用的情况是当您使用Service Workers时,此时相关的特定API是Cache Storage API https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage。 - sideshowbarker
太棒了,谢谢你。另一个答案也不错,但是你的澄清/总结非常有帮助和具体。 - Nate Anderson
2个回答

10

请记住,CORS设置并不能阻止请求到达服务器 - 这就是认证和CSRF的作用。而是防止页面读取响应。请求仍然:

  1. 从页面发送,
  2. 浏览器添加 Origin 标头,
  3. 它仍然由服务器处理(通常 - CORS与此无关,尽管可能存在其他安全性),
  4. 并在返回时,浏览器检查响应标头以获取 Access-Control-Allow-Origin。如果它与浏览器认为的 Origin 匹配,则浏览器允许页面查看请求的结果。

这就是关键 - 同源策略和CORS设置禁止协作浏览器中的页面查看响应

还要注意上面有第0步,“预检查”OPTIONS被发送以检查是否允许页面查看结果? 如果不行,那么他们假设发送请求没有什么意义-但这是一种假设。

现在回答问题

mode: no-cors 有两个作用:

  1. 它表示我不需要看到结果
  2. 因此它不发送预检查

我大概想到了以下可以使用它的情况(其中一些是恶意的)

  • 任何时候当我不需要查看响应时,如记录日志、跟踪或黑客攻击;当前端代码本质上是 try { const notNeeded = fetch(...) } catch { console.log('Tough luck, do nothing') }
  • 任何时候我想尽快将数据发送到服务器而不发送预检请求。我总是可以稍后发送带有CORS的GET请求来读取真正需要的数据。
  • 详见此答案中的缓存

提醒

CORS 会执行上述操作,但它不会执行以下操作:

  • 防止服务器处理请求 - 这是身份验证和CSRF防范的功能。
  • 防止欺骗Origin头部 - 这仅适用于配合浏览器。而作为攻击者,您通常无法访问用户使用的浏览器。因为头部可以被欺骗,所以服务器不应该将其中的数据用于安全目的。(这也是为什么通过工具(如CURL / Postman / Insomnia)测试浏览器API时,您需要检查是否有CORS标头传入,因为它们接受所有响应并且CORS策略从未应用。)

1
跳过预检OPTION请求是一个重要的区别!感谢指出。 - Nate Anderson

1
“no-cors” 模式限制了 fetch API 的操作,使其像
元素一样运行,而且还有一些“小”的额外功能,可以执行 MDN 文档所称的 "simple" 类型的请求。此外,与表单一样,响应也是不可访问的。
表单(以及所有其他 HTML 元素)可以在不使用 CORS 协议的情况下进行跨站点请求,它们的存在和行为早于 CORS 协议。
“额外功能” 是超出 HTML 元素所能实现的简单请求的那些功能:使用 HEAD 方法、更改简单头的值、设置/更改简单内容类型的parameters,如 charset。
我认为no-cors模式存在是为了支持由HTML元素发起的请求的实现。 MDN文档mode中的这个声明似乎证实了这个观点:
“然而,对于不是使用 Request() 构造函数创建的请求,通常使用 no-cors 作为 mode;例如,对于从标记开始初始化请求的嵌入资源,除非存在 crossorigin 属性,在大多数情况下使用 no-cors 模式进行请求 - 即对于 或

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