Nodejs websocket 中的 cookie问题
Nodejs websocket 中的 cookie问题
同样的一份代码
var ws = new WebSocket('ws://' + window.location.host + window.location.pathname);
chrome的header 无cookie
firfox的header 有cookie
为什么chrome ws请求header中没有cookie呢,有牛人能给我解答下么? 如何才能让chrome ws请求header中有cookie呢??
chrome中的header信息
GET ws://localhost:4567/games/matching-game/1 HTTP/1.1
Pragma: no-cache
Origin: http://localhost:4567
Host: localhost:4567
Sec-WebSocket-Key: 9NJMQbfnt2FSN2b2MkQ9cQ==
Upgrade: websocket
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Cache-Control: no-cache
Connection: Upgrade
Sec-WebSocket-Version: 13
firefox中的header
GET /games/matching-game/1 HTTP/1.1
Host: localhost:4567
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://localhost:4567
Sec-WebSocket-Key: iTKGrDte+JmWeHmpHnFCpQ==
Cookie: rack.session=BAh7CUkiD3Nlc3Npb25faWQGOgZFRiJFODNiOTA0NmJmZDcwNDM0NjVlYjNl%0AMGU3YThiNjU1OGM1ODkxZmYwYWVjOGFhNDUwOGVlN2QxMTdjOGRlMDEzMEki%0ADXRyYWNraW5nBjsARnsISSIUSFRUUF9VU0VSX0FHRU5UBjsARiItNTA1OTFk%0AZWE0YTk3MGM2ZGM2ODhhNzEzZTFlNWUyZWRlMzEzYzA3NUkiGUhUVFBfQUND%0ARVBUX0VOQ09ESU5HBjsARiItYTBiZmM4NzZkNjhmZTdhZWE3MDBkYTVlYTg5%0AMjVhYmFjNmYyZjc5NEkiGUhUVFBfQUNDRVBUX0xBTkdVQUdFBjsARiItNTBj%0AYTM5YWY5NDU1ZTM1NmY2ZTlkOTRjZjU4NzE4ZTQzNzdhZjI5NEkiCWNzcmYG%0AOwBGIkU1Yzk1ZTQ5NTlhN2YwNjVhZDE2YTA1ZWYyMjFkMWY0ODNjMzc1Yzlh%0ANWQxZDQ4NmFhMThhYmRjYjA5ZDE1OTRlSSIMdXNlcl9pZAY7AEZpBg%3D%3D%0A--8122297af5825b47cfae2bf8f30342551dfba2a4
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Node.js WebSocket 中的 Cookie 问题
在使用 WebSocket 连接时,不同浏览器对 Cookie 的处理方式可能会有所不同。例如,Chrome 和 Firefox 在处理 WebSocket 请求时的行为就存在差异。
问题描述
在同一份代码中:
var ws = new WebSocket('ws://' + window.location.host + window.location.pathname);
- Chrome 的 WebSocket 请求头中没有 Cookie。
- Firefox 的 WebSocket 请求头中有 Cookie。
原因分析
这是因为 WebSocket 协议本身并不直接携带 HTTP Cookies。当 WebSocket 连接建立时,浏览器会根据当前页面的 Cookie 状态决定是否将 Cookie 发送到 WebSocket 服务器。这取决于浏览器的实现细节以及安全策略。
解决方案
要确保 WebSocket 请求包含 Cookie,可以采取以下几种方法:
-
手动设置 Cookie 可以通过 JavaScript 手动将 Cookie 设置到 WebSocket 的请求头中。但需要注意的是,这种方式依赖于浏览器的支持。
const socket = new WebSocket('ws://' + window.location.host + window.location.pathname); // 获取当前页面的 Cookie const cookies = document.cookie.split(';').reduce((acc, cookie) => { const [name, value] = cookie.trim().split('='); acc[name] = value; return acc; }, {}); // 设置自定义 Header socket.onopen = () => { socket.send(JSON.stringify({ type: 'set-cookie', data: cookies })); };
-
使用带有 Cookie 的 HTTP 请求 先通过 HTTP 请求获取 Cookie,然后再通过 WebSocket 连接发送 Cookie。
fetch('http://localhost:4567/', { credentials: 'include' }).then(response => { if (response.ok) { return response.text(); } }).then(data => { var ws = new WebSocket('ws://' + window.location.host + window.location.pathname); ws.onopen = () => { ws.send(JSON.stringify({ type: 'set-cookie', data: document.cookie })); }; });
-
服务器端处理 如果你有权限修改服务器端代码,可以在 WebSocket 握手过程中从 HTTP 请求头中提取 Cookie 并将其传递给 WebSocket 连接。
const WebSocket = require('ws'); const express = require('express'); const app = express(); app.use(express.json()); app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Credentials', 'true'); res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4567'); next(); }); app.get('/', (req, res) => { res.send('Hello World!'); res.cookie('test', 'value', { httpOnly: false }); }); const wss = new WebSocket.Server({ server: app.server }); wss.on('connection', (ws, req) => { const cookies = req.headers.cookie; console.log(cookies); // 输出 Cookie ws.send(JSON.stringify({ type: 'cookie-received', data: cookies })); }); app.listen(4567, () => { console.log('Server is running on port 4567'); });
以上方法可以帮助你在 Chrome 浏览器中确保 WebSocket 请求包含 Cookie。希望这些示例代码和解释对你有所帮助!
没有人能给解释下么?
你服务端用的什么库?跟踪查看下请求信息
既然建立了socket连接,只要不断开,双方就可以互发数据。想要cookie只要服务端告诉客户端,我需要cookie,客户端send一下document.cookie,服务器就收到了。也许服务器不需要cookie呢。那firefox不是白发了?
继续说两句,cookie和session是为了解决http这种无状态的协议而产生的。socket一直保持连接,不需要cookie这种东西。换个思路,cookie只能保存64K的内容。而HTML5本地存储可以保存1M-5M的内容。如果服务器需要,也可以通过socket把本地存储的内容发送到服务器,发挥更多作用。
我也这样觉得, 只有想要 ws 共享原有的 cookie 登陆信息时才会两个弄一起 一般用的时候单纯用 ws 就能保证登录功能了
我想知道connection 绑定登录用户的问题解决了吗,我现在也要解决这个问题。
Chrome 和 Firefox 在处理 WebSocket 连接时对 Cookie 的处理方式不同。默认情况下,浏览器不会将 HTTP Cookie 自动发送到 WebSocket 连接中。为了在 WebSocket 请求中包含 Cookie,需要显式地设置。
示例代码
假设你使用的是 ws
模块来创建 WebSocket 客户端,你可以通过自定义握手过程来传递 Cookie。
客户端代码
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:4567/games/matching-game/1', {
headers: {
'Cookie': 'rack.session=BAh7CUkiD3Nlc3Npb25faWQGOgZFRiJFODNiOTA0NmJmZDcwNDM0NjVlYjNl%0AMGU3YThiNjU1OGM1ODkxZmYwYWVjOGFhNDUwOGVlN2QxMTdjOGRlMDEzMEki%0ADXRyYWNraW5nBjsARnsISSIUSFRUUF9VU0VSX0FHRU5UBjsARiItNTA1OTFk%0AZWE0YTk3MGM2ZGM2ODhhNzEzZTFlNWUyZWRlMzEzYzA3NUkiGUhUVFBfQUND%0ARVBUX0VOQ09ESU5HBjsARiItYTBiZmM4NzZkNjhmZTdhZWE3MDBkYTVlYTg5%0AMjVhYmFjNmYyZjc5NEkiGUhUVFBfQUNDRVBUX0xBTkdVQUdFBjsARiItNTBj%0AYTM5YWY5NDU1ZTM1NmY2ZTlkOTRjZjU4NzE4ZTQzNzdhZjI5NEkiCWNzcmYG%0AOwBGIkU1Yzk1ZTQ5NTlhN2YwNjVhZDE2YTA1ZWYyMjFkMWY0ODNjMzc1Yzlh%0ANWQxZDQ4NmFhMThhYmRjYjA5ZDE1OTRlSSIMdXNlcl9pZAY7AEZpBg%3D%3D%0A--8122297af5825b47cfae2bf8f30342551dfba2a4'
}
});
ws.on('open', function open() {
console.log('Connected');
});
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
服务器端代码
服务器端需要能够接收并处理这些 Cookie。这里以一个简单的 Node.js WebSocket 服务器为例:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 4567 });
wss.on('connection', function connection(ws, req) {
console.log('headers:', req.headers);
const cookies = req.headers.cookie;
if (cookies) {
console.log('Cookies received:', cookies);
} else {
console.log('No cookies received');
}
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
});
解释
- 客户端:在连接 WebSocket 时,通过设置
headers
属性中的Cookie
来显式传递 Cookie。 - 服务器端:通过
req.headers
获取请求头中的 Cookie,并进行处理。
这种方式可以确保在 Chrome 和 Firefox 中都能正确地传递 Cookie。