我需要发送一个带有websocket握手请求的cookie,以确保负载均衡器将请求路由到特定的后端。在Firefox,Safari和websocket-sharp中可以正常使用,但是我无法让Chrome发送带有websocket握手请求的cookie。
我在负载均衡器(Traefik)中启用了粘性会话,并使用现有的SockJS代码在Firefox和Safari上“正常工作”。
第一个请求没有cookie,并且负载均衡器在握手响应(101个交换协议)上设置一个。随后的Websocket握手请求将发送cookie,并且所建立的Websocket连接将建立到正确的后端。
在我的websocket-sharp客户端中,我在打开连接之前显式设置了cookie,它可以按预期工作。
Chrome永远不会发送带有Websocket握手请求的Cookie。我尝试了现有的SockJS,其中cookie由负载均衡器在其他请求上设置,或者在发送Websocket请求的文档中显式设置,然后立即发送请求。
我尝试了简单的key=val
cookie,以及具有其他各种选项集组合的cookie,例如path
,domain
,max-age
,secure
,samesite
等
在任何站点(例如https://www.google.com)上的Chrome开发工具控制台中,执行:
document.cookie = 'key=val'
new WebSocket('wss://www.google.com')
请注意,如果在wss
上浏览页面,则方案必须为https
;在ws
上浏览页面时,方案必须为http
。另外,如正在生成的请求中的origin
标头所示,域和端口在正在查看的页面和Websocket的URL中是相同的。
检查结果请求(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来解释所观察到的行为。
答案 0 :(得分:0)
更新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,所以我不在乎,但是也许这样做的人可以在Firefox中执行个人资料之类的事情,并在启用此选项的情况下创建开发者,而永远不会Facebook。
具体来说,在我的Chrome版本中,它位于非常狭窄的汉堡菜单->设置->高级->内容设置...-> Cookies->第一个切换选项(在“允许保存和读取网站之间切换Cookie数据(推荐)”和“已阻止”)。或单击地址栏中的cookie图标,然后单击管理。
我正在Debian 9中使用Linux版本的Chrome版本73.0.3683.86(正式版本)(64位)。您似乎正在使用Mac OS,因此如果这些版本是有点相关。在Windows版本中似乎没有出现此问题,但是我不是自己使用它或对其进行测试的人,它可能会更旧(我可以在以后发现时进行编辑)。它也可以在Android(版本73.0.3683.90)中使用,但是似乎没有一个选项可以首先阻止cookie。
我也尝试了各种设置,但不确定5字形修饰符是否可以检查14000次,但已经有很多天试图弄清这一点。我一遍又一遍地分析了标头和两端的代码,以为可能是Cookie域/路径/到期/ httponly /安全/相同站点,不匹配的域,证书问题,服务器设置等,等等,但是没有,这是一个愚蠢的复选框。至少我可以继续,而不必等待Google对其进行修复...
答案 1 :(得分:0)
cookie可能实际上是在WebSocket Request标头中发送的,只是没有显示在dev-tool中。 Chrome NetLog可以跟踪它。根据他们在此Chromium issue中的建议:
Cookie故意从devtools中显示的标头中过滤掉。这是因为它们是通过渲染器传递的,该渲染器不应访问HttpOnly cookie。
答案 2 :(得分:0)
尝试打开chrome://flags
,并禁用SameSite by default cookies
和Cookies without SameSite must be secure
这两个配置。
您可以通过 Wireshark 或任何抓包工具在请求头中看到 cookie,但在 chrome 的开发工具中看不到 cookie。