【问题标题】:How do I make Chrome send cookies with WebSocket handshake request?如何让 Chrome 使用 WebSocket 握手请求发送 cookie?
【发布时间】:2019-08-17 10:17:52
【问题描述】:

我需要发送一个带有 websocket 握手请求的 cookie,以确保负载均衡器将请求路由到特定的后端。这在 Firefox、Safari 和 websocket-sharp 中运行良好,但我无法让 Chrome 使用 websocket 握手请求发送 cookie。

我在我的负载均衡器 (Traefik) 中启用了粘性会话,它在 Firefox 和 Safari 上使用我现有的 SockJS 代码“正常工作”。

第一个请求没有 cookie,负载均衡器在握手响应上设置了一个(101 切换协议)。随后的 websocket 握手请求发送 cookie,生成的 websocket 连接建立到正确的后端。

在我的 websocket-sharp 客户端中,我在打开连接之前明确设置了 cookie,它按预期工作。

Chrome 从不发送带有 websocket 握手请求的 cookie。我尝试了现有的 SockJS,使用负载均衡器在其他请求上设置的 cookie,或者在发送请求之前立即在发出 websocket 请求的文档中明确设置。

我尝试了简单的key=val cookie,以及带有各种其他选项组合的 cookie,例如pathdomainmax-agesecuresamesite

在任何站点(例如https://www.google.com)的 Chrome 开发工具控制台中,执行:

document.cookie = 'key=val'
new WebSocket('wss://www.google.com')

请注意,如果在https 上查看页面,则方案必须为wss,在http 上查看页面时,方案必须为ws。此外,正在查看的页面和 websocket 的 URL 中的域和端口是相同的,如生成的请求中的 origin 标头中所述。

检查生成的请求(400 错误请求 - 我只关心为此测试生成的请求,而不是结果),它显示:

GET wss://www.google.com/ HTTP/1.1
Host: www.google.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: https://www.google.com
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Sec-WebSocket-Key: HrtpryMAlu5yjGCNgxzcpw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

在 Firefox 中做同样的事情,cookie 与握手请求一起发送:

Host: www.google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Sec-WebSocket-Version: 13
Origin: https://www.google.com
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: QvNsHgLE5znjaUG04RFdPA==
DNT: 1
Connection: keep-alive, Upgrade
Cookie: <SNIPPED>; key=val
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

还有 Safari:

Connection: Upgrade
Host: www.google.com
Origin: https://www.google.com
Cookie: key=val; <SNIPPED>
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: zQEpYp+yzf5EQmQSb71B6g==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15

我希望生成的请求包含浏览器已知的匹配来源的所有文档 cookie。

我在网上找到了一些参考资料,似乎表明“现代浏览器,包括 Chrome”应该是这种情况:

我发现一个似乎表明 Chrome 不会随握手请求一起发送 cookie 的参考资料:

我在 Chrome 中找不到任何官方文档或更改来解释观察到的行为。

【问题讨论】:

    标签: google-chrome cookies websocket


    【解决方案1】:

    更新 2:我将复制我通过错误报告发现的内容:

    使用 UI 阻止 cookie 并编辑我的域的白名单例外(与禁用 cookie 的选项相同的位置)我发现以下内容:

    wss://example.com 是“无效网址”,无法添加。

    为方案输入 *:// 或为端口输入 :* 是可能的,但会从字符串中删除,导致:

    *://[*.]example.com:443 -> [*.]example.com:443 - 不起作用

    *://[*.]example.com:* -> [*.]example.com - 有效

    *://example.com:* -> example.com - 工作


    更新 1:我提交了一份错误报告并已得到确认:

    https://bugs.chromium.org/p/chromium/issues/detail?id=947413


    对我有用的是在设置中全局允许 cookie。

    是的,这是一种非常有效的解决方法,因为我永远不会将允许每个 cookie 放入浏览器的方法称为可接受的解决方案,但我很确定这是一个错误。我知道它曾经在不久前使用 cookie 阻止 + 白名单来工作,但是当我将它单独放置 x 周时,某些版本破坏了它。抱歉,不知道是哪个...我不使用 Chrome,所以我真的不在乎,但也许那些使用 Chrome 的人可以在 Firefox 中执行类似配置文件的操作,并在启用此选项的情况下创建一个开发版本,而永远不要去脸书。

    具体来说,在我的 Chrome 版本中,它位于非常狭窄的汉堡菜单 -> 设置 -> 高级 -> 内容设置... -> Cookies -> 第一个切换选项(在“允许网站保存和阅读”之间切换cookie 数据(推荐)”和“已阻止”)。或者点击地址栏中的 cookie 图标,然后点击管理。

    我在 Debian 9 中使用 Chrome 版本 73.0.3683.86(官方构建)(64 位)的 Linux 版本。看起来您使用的是 Mac OS,所以如果这些版本是有点相关。在 Windows 版本中似乎没有出现这个问题,但是我不是使用它或自己测试它的人,它可能更旧(我可以稍后在我发现时进行编辑)。它也适用于 Android(版本 73.0.3683.90),但它似乎一开始就没有阻止 cookie 的选项。

    我也尝试了各种设置,我不确定使用五元组的修饰词来检查 14000 次,但我花了很多天时间才弄清楚这一点。我一遍又一遍地分析了两端的标头和代码,并认为它可能是 cookie 域/路径/到期/httponly/secure/samesite、不匹配的域、证书问题、服务器设置等,等等,但是没有,这是一个愚蠢的复选框。至少我可以继续,不必等待谷歌修复它......

    【讨论】:

    • 无论被阻止/列入白名单的域如何,我都无法让 Chrome 发送带有 websocket 握手请求的 cookie。我正在使用具有默认设置(允许 cookie,推荐)的 Chrome,并且没有将任何域列入白名单。您是说我在上面的问题中描述的测试在默认设置下适用于您,但仅不适用于被阻止的 cookie 和列入白名单的域?
    • 是的,这就是我正在发生的事情,我在 Windows 10 中检查了相同版本的 Chrome,它也在执行此操作。可能一文不值我在 Chrome 上遇到了一些其他问题,这些问题通过清除用户配置文件并让它创建一个新配置文件(例如 Linux 中的 ~/.config/google-chrome)得到了解决。也许这会有所帮助。
    【解决方案2】:

    很可能 cookie 实际上是在 WebSocket 请求标头中发送的,只是没有显示在开发工具中。 可以通过Chrome NetLog追踪。根据他们在Chromium issue 中的建议:

    Cookie 是有意从 devtools 中显示的标题中过滤出来的。这是因为它们是通过渲染器传递的,它不应该访问 HttpOnly cookie。

    【讨论】:

    • 我很难理解 wss:// 是如何理解要生成什么令牌的,结果证明这一直是使用 cookie 标头完成的。但是 chrome devtools 只是没有显示它!我无法想象它会那样做。至少他们可以对 Cookie: 标头内容使用 * 符号或其他符号,而不是完全隐藏标头,从而无法区分它是否存在。感谢 glob Firefox 显示标题。
    【解决方案3】:

    只需尝试打开chrome://flags,并禁用SameSite by default cookiesCookies without SameSite must be secure这两个配置。

    您可以通过 Wireshark 或任何数据包捕获工具在请求标头中看到 cookie,但您无法在 chrome 的开发工具中看到 cookie。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多