【问题标题】:CORS error if PUT has credentials 'include' and Content-Type at the same time如果 PUT 同时具有凭据“包含”和 Content-Type,则出现 CORS 错误
【发布时间】:2021-09-02 11:06:30
【问题描述】:

我正在使用带有以下选项的 JavaScript fetch()

window.fetch(path, {
    method: 'PUT',
    headers: {'Content-Type': 'application/json'},
    mode: 'cors',
    credentials: 'include',
    redirect: 'follow',
    referrerPolicy: 'no-referrer',
    cache: 'no-cache',
    body: JSON.stringify(data)
})

但我得到错误:

Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

我的Access-Control-Allow-Headers 有通配符*

无需凭据即可工作

如果我不添加 credentials: include 并在 API 服务器上关闭身份验证,它可以正常工作。

它可以在没有 Content-Type 的情况下工作

如果我不添加 headers: {'Content-Type': 'application/json'}, 并在 API 服务器上保持 auth ON,它工作正常。这意味着它是使用text/plain;UTF-8 发送的,但内容仍然是 JSON。


标题

来自我的 API 服务器的标头:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers: *

http://localhost:3000 是我的前端应用程序在哪里运行。


提示

  • 如果我收到此错误,Chrome 中的 devTools 将无法向我显示响应标头(Access-Control-Allow-Headers 等),并且请求标头显示 Provisional headers are shown,其中只有 content-type: application/json一般没有method: PUT(完全没有方法)。所以看起来 Chrome 在触发前停止了它。
  • 服务器位于不同的域(实习生网络)上,并在 httpSameSite: None 没有 Secure 上运行,但我在 Chrome 中禁用了安全性 Cookies without SameSite must be secure 以便在开发模式下绕过它。

credentialscontent-typePUT之间有什么关系吗?是否可以发送PUTcredentialsapplication/json?如果不可能 - 我应该如何使用 PUT 方法发送数据? FormData 允许 cors 的内容类型不受 PUT 支持。

【问题讨论】:

  • 当您的请求不是“简单”请求时,会发送预检。服务器必须相应地响应预检。预检是一个 OPTIONS 请求,而不是一个 PUT 请求,它将与 PUT 请求分开显示。
  • @KevinB 我知道我已经与 OPTIONS 斗争了很长时间,但所有 preflights 都处理得很好,并且它们在 DevTools 中有 method: OPTIONS - 所以我可以调试它们.这个请求中没有任何从 Chrome 发出的方法,并且只发生在 credentials 上。
  • 您的错误表明您的预检并未表明给定端点允许内容类型。您在客户端上所做的任何事情都无法解决这个问题
  • @KevinB 正如你所说,我开始深入研究预检响应,并尝试设置Access-Control-Allow-Headers: Content-Type 而不是Access-Control-Allow-Headers: * 通配符,它​​有效。在 MDN 上没有找到任何关于它的信息,我不确定这是否是正确的原因。

标签: javascript api cors


【解决方案1】:

MDN documentation for Access-Control-Allow-Headers

* 仅算作没有凭据的请求(没有 HTTP cookie 或 HTTP 身份验证信息的请求)的特殊通配符值。在带有凭据的请求中,它被视为文字标头名称*,没有特殊语义。请注意,Authorization 标头不能使用通配符,并且始终需要明确列出。

您需要明确指定要允许的标头。

【讨论】:

    【解决方案2】:

    Access-Control-Allow-Headers 从通配符 * 更改为显式 Content-Type 对我有用。

    【讨论】:

      猜你喜欢
      • 2020-10-09
      • 2023-02-15
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      相关资源
      最近更新 更多