移动体验 / 方法解读

移动端 fetch 请求携带 Cookie 失败如何排查

当移动端网页发起跨域请求时,如果服务器返回的 Access-Control-Allow-Origin 响应头值为星号,将导致无法携带凭证信息。

检查请求是否携带凭证

在移动端浏览器开发者工具的 Network 面板中,找到对应的跨域请求。查看请求头中是否存在 Cookie 字段。如果请求头中没有 Cookie,说明客户端在发起请求时未设置凭证标志。对于 Fetch API,需要确认 Request.credentials 的值是否为 'include'。对于 XMLHttpRequest,需要确认是否设置了 withCredentials 属性为 true。只有当客户端明确请求携带凭证时,服务器端的 CORS 配置才会生效。

如果请求头中确实存在 Cookie,但请求状态显示失败或响应数据不完整,则问题可能出在服务器配置。此时需要检查服务器的响应头。如果 Access-Control-Allow-Origin 的值为星号,浏览器会拦截响应,因为星号通配符与凭证请求不兼容。这是浏览器安全机制,旨在防止跨站请求伪造攻击。服务器必须返回具体的域名地址,而不是星号,才能允许凭证通过。

确认服务器 CORS 响应头配置

在服务器端配置中,必须将 Access-Control-Allow-Origin 的值修改为具体的请求来源域名。例如,将 Access-Control-Allow-Origin 设置为 https://example.com,而不是 *。同时,服务器还需要返回 Access-Control-Allow-Credentials: true 响应头。这两个配置必须同时存在,浏览器才会允许跨域请求携带 Cookie。如果只设置了 Access-Control-Allow-Origin 为具体域名,但没有设置 Access-Control-Allow-Credentials 为 true,请求依然会失败。

除了上述两个核心响应头,服务器还应正确设置 Access-Control-Allow-Methods 和 Access-Control-Allow-Headers。虽然这些头主要影响预检请求,但如果配置错误,也会导致请求被拦截。在移动端开发中,由于网络环境复杂,服务器端日志记录非常重要。通过查看服务器日志,可以确认是否收到了带有凭证的请求,以及服务器是否正确返回了 CORS 相关的响应头。

客户端代码修正方法

如果服务器配置暂时无法修改,可以在客户端代码中调整请求方式。对于 Fetch API,确保 Request.credentials 设置为 'include'。代码示例为:fetch(url, { credentials: 'include' })。对于 XMLHttpRequest,确保 withCredentials 设置为 true。代码示例为:xhr.withCredentials = true。对于 Server-sent events,确保 EventSource 构造函数的第三个参数中 withCredentials 设置为 false,因为默认值已经是 false。

需要注意的是,客户端的修改只能解决部分问题。如果服务器端 Access-Control-Allow-Origin 仍然是星号,客户端无论怎么设置,都无法成功获取数据。这是因为浏览器安全策略限制了星号通配符与凭证的兼容性。因此,最根本的解决方案还是修改服务器端的 CORS 配置。客户端代码的调整主要是为了确保请求确实发出了凭证标志,以便服务器能够识别并处理。

验证修复结果

修改服务器配置或客户端代码后,刷新移动端网页并重新发起请求。再次打开开发者工具的 Network 面板,查看请求状态。如果请求成功,响应头中应该包含 Access-Control-Allow-Origin 的具体域名值,以及 Access-Control-Allow-Credentials: true。同时,请求头中的 Cookie 应该被正确发送,并且响应数据能够正常显示在页面上。

如果请求仍然失败,可以尝试清除浏览器缓存并重新加载页面。有时候,浏览器会缓存之前的错误响应头。清除缓存后,浏览器会重新向服务器发送请求,并获取最新的响应头。如果问题依旧存在,建议检查服务器日志,确认服务器是否正确处理了请求,以及是否正确返回了 CORS 响应头。通过逐步排查,可以定位并解决移动端 fetch 请求携带 Cookie 失败的问题。

资料与延伸阅读

你可以通过以下原始资料核对文中概念,并继续深入阅读。

  1. Reason: Credential is not supported if the CORS header 'Access-Control-Allow-Origin' is '*' - HTTP | MDN ↗
← 更多移动体验文章返回顶部 ↑