Node.js中WebSocket带密钥连接实现及防未授权连接疑问
WebSocket连接阶段验证密钥,阻止未授权连接
核心原理:WebSocket的HTTP握手机制
WebSocket连接并非直接建立,而是先通过HTTP握手完成协议升级:
- 客户端发起
GET请求,携带Upgrade: websocket、Connection: Upgrade等标准头,同时你可以自定义添加验证头。 - 服务器收到请求后,先验证授权信息,通过则返回
101 Switching Protocols完成升级;不通过直接返回403 Forbidden并关闭连接,从根源上拒绝无效请求。
你关心的两个问题
- Node.js WebSocket是否发送连接消息?:是的,就是初始的HTTP握手请求,这是连接的必经步骤。
- 能否修改该消息?:可以,客户端可以添加自定义请求头;服务器可以在握手阶段读取并验证这些头,决定是否允许升级。
实现方案:握手阶段验证密钥
这种方式能避免客户端先建立连接再验证的安全隐患,直接拦截未授权请求,防止DDOS攻击。
服务器端(基于ws库,Node.js常用WebSocket库)
const WebSocket = require('ws'); const http = require('http'); // 创建HTTP服务器 const server = http.createServer((req, res) => { res.writeHead(404); res.end(); }); // 初始化WebSocket服务器,禁用自动升级 const wss = new WebSocket.Server({ noServer: true }); // 监听HTTP升级事件,处理WebSocket握手 server.on('upgrade', (request, socket, head) => { // 从请求头获取自定义验证密钥 const authKey = request.headers['x-auth-key']; // 验证密钥有效性 if (!authKey || authKey !== '你的预设密钥') { // 验证失败,返回403并关闭连接 socket.write('HTTP/1.1 403 Forbidden\r\n\r\n'); socket.destroy(); return; } // 验证通过,完成WebSocket协议升级 wss.handleUpgrade(request, socket, head, (ws) => { wss.emit('connection', ws, request); }); }); // 处理已授权的WebSocket连接 wss.on('connection', (ws) => { console.log('客户端已授权连接'); ws.on('message', (data) => { ws.send('收到消息:' + data.toString()); }); }); server.listen(8080);
客户端代码(添加自定义请求头)
// 创建WebSocket时携带验证密钥头 const socket = new WebSocket('wss://server.com/server/', { headers: { 'X-Auth-Key': '客户端持有的密钥' } }); socket.addEventListener('open', (e) => { console.log('已成功建立授权连接'); }); socket.addEventListener('error', (e) => { console.log('连接失败:密钥无效或未授权'); });
为什么比连接后验证更安全
- 握手阶段直接拒绝,不会建立WebSocket连接,服务器无需为无效请求维护连接资源,彻底避免恶意客户端通过大量空连接耗尽服务器资源。
- 之前的“连接后发登录请求”方式,客户端已经占用了服务器的连接数,恶意攻击者可以轻松发起DDOS攻击。
补充注意事项
- 生产环境必须使用
wss(WebSocket over TLS),避免密钥明文传输。 - 也可以通过URL查询参数传递密钥(如
wss://server.com/server/?key=xxx),服务器从request.url解析,但请求头的方式更隐蔽。
内容的提问来源于stack exchange,提问作者user2980746
相关产品推荐
相关产品推荐

