为什么在 Chrome 中预检 OPTIONS 请求的认证 CORS 请求可以正常工作,但在 Firefox 中却不行?

阅读时长 4 分钟读完

CORS(跨源资源共享)是一种机制,它允许网页服务器向其他域发送 AJAX 请求。CORS 请求分为简单请求和复杂请求两种类型。对于简单请求,浏览器会自动处理跨域问题;而对于复杂请求,则需要进行预检(preflight)。

预检请求是指浏览器在发送实际请求之前,先向服务器发送一个 OPTIONS 请求,以获知服务器是否支持该请求。如果服务器允许该请求,浏览器才会发送实际请求。

问题描述

在使用认证信息(如 cookie、Authorization 头等)进行 CORS 请求时,Chrome 和 Firefox 的表现存在差异。具体来说,当我们向一个需要认证信息的跨域接口发送请求时,Chrome 可以正确地发送预检请求,并在预检请求中带上认证信息。而 Firefox 则无法发送带有认证信息的预检请求,从而导致实际请求被拒绝。

这个问题的具体原因与浏览器的实现方式有关。在 Chrome 中,当使用认证信息进行 CORS 请求时,预检请求会带上 Access-Control-Allow-Credentials 头,并且只有在该头存在的情况下才会带上认证信息。而在 Firefox 中,无论是否存在 Access-Control-Allow-Credentials 头,预检请求都不会带上认证信息。

解决方案

针对这个问题,我们有两种解决方案:

1. 添加 CORS 配置

可以在服务器端添加 CORS 配置,指定允许的 HTTP 方法、头信息以及是否允许携带认证信息。以下是一个示例代码:

在这个示例中,我们允许所有域名访问该接口,并允许 GET、POST、PUT、DELETE 和 OPTIONS 这几种 HTTP 方法。我们还允许携带 Content-TypeAuthorization 这两个头信息,并设置了 Access-Control-Allow-Credentials 头为 true,以允许携带认证信息。

2. 取消携带认证信息

如果不能修改服务器端的配置,我们也可以取消在跨域请求时携带认证信息。具体来说,在发送实际请求时,将 withCredentials 属性设置为 false,即可取消携带认证信息:

-- -------------------- ---- -------
------------------------------- -
  ------- -------
  -------- -
    --------------- -------------------
    ---------------- ------- -------
  --
  ------------ ---------- -- --- -------------
  ----- ----------------
    ----- ----- ----
  --
---------------- -- -
  ----------------------
---

在这个示例中,我们将 credentials 属性设置为 'include',以允许携带认证信息。如果要取消携带认证信息,则将 credentials 属性设置为 'omit' 或者不设置即可。

总结

在实际开发过程中,我们需要注意浏览器对 CORS 请求的处理方式。尤其是在涉及到认证信息的情况下,Chrome 和 Firefox 的表现可能存在差异。只有深入了解浏览器的实现方式,并根据具体情况选择合适的解决方案,才能确保跨域请求的正常工作。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/605427b78d846479e750aa3c

纠错
反馈