y-websocket 安全实践:基于 Cookie 与 Header 的现有认证机制集成指南
【免费下载链接】y-websocketWebsocket Connector for Yjs项目地址: https://gitcode.com/gh_mirrors/yw/y-websocket
y-websocket 安全实践:在开始集成认证之前,先认识这个项目——它是 Yjs 实时协同生态中最常用的 WebSocket 连接器(Websocket Connector for Yjs),负责在客户端与服务器之间同步协同文档与在线状态。默认的演示服务器对任何知道房间名的人开放,直接上生产存在数据泄露风险。本文提供一套基于 Cookie 与 Header 的现有认证机制集成指南,覆盖服务端握手校验、客户端 Token 传递与刷新、连接后二次鉴权,并附上可照抄的代码片段。更多 API 说明见官方文档 README.md。
为什么 y-websocket 需要接入现有认证机制
y-websocket 的定位是"连接层",本身不负责业务账号体系。仓库自带的演示服务器(bin/server.cjs)是纯内存实现,只要有人猜到或泄露了房间名(roomname),就能直接连接并读写协同数据。对于文档协作、白板、在线表格这类产品,这意味着:
- ⚠️ 未授权用户可读取房间内的全部协同内容;
- ⚠️ 未授权用户可向房间注入恶意更新;
- ⚠️ 没有身份标识,无法做只读/可写/管理员等权限分级。
因此,把 y-websocket 接入你现有的认证机制(Session、Cookie、JWT 等)是上线前必须完成的一步。好消息是:WebSocket 握手本身就是一次 HTTP 请求,天然支持 Cookie 与 Header,官方文档也明确指出"WebSocket 会发送请求头与 Cookie,可以直接复用现有认证机制"(README.md)。
先看懂连接流程:认证校验应该放在哪一步
客户端创建WebsocketProvider时,会拼接出最终连接地址:serverUrl + '/' + roomname + '?' + 查询参数(见 src/y-websocket.js 的urlgetter)。随后浏览器发起 WebSocket 握手,这是一次携带 Cookie 和请求头的 HTTP Upgrade 请求。
服务端的校验入口在 bin/server.cjs 的upgrade事件中:先校验身份,通过后再调用wss.handleUpgrade升级连接,否则直接销毁 socket。这个位置就是 y-websocket 认证集成的核心改造点。
方案一:y-websocket 基于 Cookie 的认证集成
Cookie 认证原理:同源 WebSocket 自动携带会话
当页面与 y-websocket 服务同域部署(如统一走wss://api.example.com反向代理)时,浏览器会在 WebSocket 握手请求中自动附带当前域的 Cookie。这意味着客户端代码几乎零改动,你现有的 Session/Cookie 登录体系直接生效,这也是最省事的 y-websocket 认证集成方式。
服务端改造:在 upgrade 事件中校验 Cookie
server.on('upgrade', (request, socket, head) => { // 从请求头取出 Cookie,调用你现有的会话校验逻辑 if (!isValidSession(request.headers.cookie)) { socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n') socket.destroy() // 握手失败,立即拒绝 return } wss.handleUpgrade(request, socket, head, ws => { wss.emit('connection', ws, request) }) })要点:isValidSession可以直接复用你 Web 应用里解析 Session Cookie 的函数,无需为 WebSocket 另写一套登录逻辑。
跨域场景的注意点
Cookie 方案依赖同源。如果页面和 y-websocket 服务分属不同域名,浏览器不会自动携带 Cookie,此时建议切换到方案二,或通过反向代理让 WebSocket 与页面同源。
方案二:y-websocket 基于 Header 的认证集成(Token 方案)
浏览器限制:WebSocket API 无法自定义 Header
很多人以为可以在浏览器里给 WebSocket 加Authorization头,但原生 WebSocket API 并不支持自定义请求头。因此"Header 认证"在浏览器端有两类等价实现,服务端都能从握手请求中读到。
路径一:用 protocols 子协议传递 Token
protocols选项会映射为握手请求的Sec-WebSocket-Protocol请求头(客户端配置见 src/y-websocket.js):
const provider = new WebsocketProvider('wss://collab.example.com', 'room-a', doc, { protocols: ['bearer', 'eyJhbGciOiJIUzI1NiJ9...'] // 子协议中携带 Token })服务端读取:
const proto = request.headers['sec-websocket-protocol'] || '' const token = proto.startsWith('bearer') ? proto.split(', ')[1] : null路径二:用 params 查询参数传递 Token,支持定时刷新
更常见的是把 Token 放进查询参数,服务端从request.url中解析:
const provider = new WebsocketProvider('wss://collab.example.com', 'room-a', doc, { params: { token: 'eyJhbGciOiJIUzI1NiJ9...' } }) // Token 即将过期时直接更新,下次重连自动携带新值 provider.params.token = 'new-token'provider.params可以在运行期安全更新,新的值会在下一次(重)连接时生效,非常适合短时效 Token 的场景。服务端解析方式:
const token = new URL(request.url, 'http://localhost').searchParams.get('token')Node.js 客户端如何认证
Node.js 端通过WebSocketPolyfill: require('ws')使用 ws 包,而 ws 客户端不会自动携带 Cookie,因此推荐同样走params或protocols传 Token,服务端无需区分运行环境。
连接建立后的二次校验:auth 消息机制
握手通过不等于万事大吉。y-websocket 客户端内置了对 y-protocols auth 消息(type=2)的处理(src/y-websocket.js):如果服务端在连接建立后发送鉴权拒绝消息,客户端会触发permissionDeniedHandler,在控制台输出 "Permission denied to access ..."(src/y-websocket.js)。
默认的 bin/utils.cjs 把messageAuth注释掉了,你可以在setupWSConnection中按房间维度做细粒度授权:有权限则正常同步,无权限则发送 auth 拒绝消息并关闭连接。建议把"粗粒度身份校验"放在握手阶段,把"房间级细粒度授权"放在 auth 消息阶段,两层配合。
y-websocket 认证集成的安全最佳实践清单
- ✅ 生产环境必须使用 WSS(wss://),防止 Token、Cookie 在传输中被窃听;
- ✅ Cookie 设置
HttpOnly、Secure、SameSite属性; - ✅ Token 尽量不放查询参数长期使用(URL 可能被日志记录),改用短时效 Token 并定期刷新
provider.params; - ✅ 服务端校验 roomname 格式,避免路径穿越等异常访问;
- ✅ 鉴权失败统一返回 401/403 并立即销毁 socket,减少无效连接开销;
- ✅ 为 y-websocket 服务配置连接数上限与频率限制,防止资源耗尽;
- ✅ 密钥、签名私钥等敏感信息严禁出现在前端代码中。
常见问题排查速查表
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 握手被 401/403 拒绝 | Cookie 未携带(跨域或域名不一致)、Token 过期 | 同源部署;使用短时效 Token 并定时刷新 |
| 浏览器无法设置 WebSocket 自定义 Header | 原生 WebSocket API 限制 | 改用protocols或params传递 |
| 连接成功但提示 Permission denied | 服务端 auth 消息拒绝了房间级权限 | 检查授权逻辑与messageAuth发送时机 |
| Node.js 客户端拿不到会话 | ws 客户端不自动携带 Cookie | 改用params/protocols传 Token |
总结
y-websocket 认证集成的关键,是抓住 WebSocket 握手这一"HTTP 关口":同源部署时用 Cookie 方案几乎零成本复用现有登录体系;跨域或 Token 场景下用protocols子协议或params查询参数传递凭证;再配合 auth 消息做房间级二次鉴权,就能在不改动 y-websocket 同步逻辑的前提下,为实时协同功能加上完整的安全防护。
【免费下载链接】y-websocketWebsocket Connector for Yjs项目地址: https://gitcode.com/gh_mirrors/yw/y-websocket
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考