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 方法、头信息以及是否允许携带认证信息。以下是一个示例代码:
app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Allow-Credentials', true); next(); });
在这个示例中,我们允许所有域名访问该接口,并允许 GET、POST、PUT、DELETE 和 OPTIONS 这几种 HTTP 方法。我们还允许携带 Content-Type
和 Authorization
这两个头信息,并设置了 Access-Control-Allow-Credentials
头为 true,以允许携带认证信息。
2. 取消携带认证信息
如果不能修改服务器端的配置,我们也可以取消在跨域请求时携带认证信息。具体来说,在发送实际请求时,将 withCredentials
属性设置为 false,即可取消携带认证信息:
-- -------------------- ---- ------- ------------------------------- - ------- ------- -------- - --------------- ------------------- ---------------- ------- ------- -- ------------ ---------- -- --- ------------- ----- ---------------- ----- ----- ---- -- ---------------- -- - ---------------------- ---
在这个示例中,我们将 credentials
属性设置为 'include',以允许携带认证信息。如果要取消携带认证信息,则将 credentials
属性设置为 'omit' 或者不设置即可。
总结
在实际开发过程中,我们需要注意浏览器对 CORS 请求的处理方式。尤其是在涉及到认证信息的情况下,Chrome 和 Firefox 的表现可能存在差异。只有深入了解浏览器的实现方式,并根据具体情况选择合适的解决方案,才能确保跨域请求的正常工作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/605427b78d846479e750aa3c