如何让Chrome在WebSocket握手请求中发送cookies?

10
我需要在websocket握手请求中发送一个cookie,以确保负载均衡器将请求路由到特定的后端。在Firefox、Safari和websocket-sharp中,这可以正常工作,但我无法让Chrome发送带有websocket握手请求的cookie。
我在我的负载均衡器(Traefik)中启用了粘性会话,并且使用现有的SockJS代码,在Firefox和Safari上“只需工作”。
第一个请求没有cookie,负载均衡器在握手响应(101切换协议)中设置了一个cookie。随后的websocket握手请求发送cookie,并建立到正确后端的websocket连接。
在我的websocket-sharp客户端中,我在打开连接之前明确设置了cookie,并且它按预期工作。
Chrome从未在websocket握手请求中发送cookie。我尝试使用已设置负载均衡器上其他请求或在发送请求之前立即在文档中显式设置cookie的现有SockJS。
我尝试使用简单的key=val cookie,以及设置了各种其他选项的cookie,例如pathdomainmax-agesecuresamesite等。
在Chrome开发者工具控制台上的任何网站(例如https://www.google.com),执行以下操作:
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的更改来解释所观察到的行为。
3个回答

1
更新2:我将复制通过错误报告发现的内容:
使用UI来阻止Cookie并编辑我的域名的白名单例外情况时(与禁用Cookie选项的位置相同),我发现以下内容:
wss://example.com 不是“有效的Web地址”,因此无法添加。
输入*://作为方案或:*作为端口是可能的,但会从字符串中删除,结果如下:
*://[*.]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阻止+白名单,但某个版本在我离开了几周后破坏了它。抱歉,我不知道是哪个版本...我不使用Chrome,所以我不太关心,但也许那些使用Chrome的人可以像Firefox中的配置文件一样创建一个开发配置文件,并启用此选项,永远不要去Facebook。
具体来说,在我的Chrome版本中,它位于非常狭窄的汉堡菜单下->设置->高级->内容设置...->Cookie->第一个切换选项(在“允许站点保存和读取cookie数据(推荐)”和“已阻止”之间切换)。或者单击地址栏中的cookie图标,然后单击“管理”。
我正在使用Linux版本的Chrome 73.0.3683.86(官方构建)(64位),在Debian 9上运行。看起来您正在使用Mac OS,如果这些版本有些相关,那么也许这会对您有所帮助。这个问题似乎在Windows版本中没有出现,但是我没有使用或测试它,它可能更旧(我找到后可以编辑)。它还适用于Android(版本73.0.3683.90),但是该选项似乎没有阻止cookie的功能。
我还尝试了各种设置,不确定检查14000次的五元词修饰符,但已经尝试了很多天才能弄清楚这一点。我一遍又一遍地分析头和代码,并认为它可能是cookie域/路径/到期/httponly/secure/samesite,不匹配的域,证书问题,服务器设置等等,但是,没有,只是一个愚蠢的复选框。至少我可以继续进行而不必等待Google解决它...

无论是在阻止/白名单域名的情况下,我都无法让Chrome在websocket握手请求中发送cookies。我正在使用默认设置的Chrome(允许cookies,推荐),并且没有将任何域名列入白名单。您是说我在上面描述的测试对您来说可以使用默认设置工作,但仅在阻止cookies和列入白名单的域名时不起作用吗? - mrmachine
是的,这就是我遇到的情况,并且我在Windows 10上使用相同版本的Chrome进行了检查,结果也出现了这种情况。值得注意的是,我曾经遇到过一些Chrome的问题,通过清除用户配置文件并让它创建一个新的配置文件来解决(例如在Linux中的~/.config/google-chrome)。也许这会有所帮助。 - g4rb4g3_ju1c3

1
很可能Cookie实际上是在WebSocket请求头中发送的,只是在开发工具中没有显示出来。可以通过Chrome NetLog跟踪它。从他们在Chromium issue中建议的内容来看:

故意从devtools中显示的标头中过滤掉了Cookie。这是因为它们会经过渲染器,而渲染器不应该访问HttpOnly Cookie。


我曾经很难理解wss://是如何知道要生成哪个令牌的,后来发现这是一直使用cookie头完成的。但是,Chrome开发者工具却没有显示它!我无法想象它会这样做。至少他们可以在Cookie:头内容中使用*符号或其他东西来代替完全隐藏标头,使得不可能区分它是否存在。感谢Firefox显示了该标头。 - vladimir

0

尝试打开chrome://flags,并禁用默认情况下 SameSite cookies必须安全的 SameSite cookies这两个配置。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接