NodeJS中如何防止第三方连接WebSocket(使用WS模块)
如何为WS模块的WebSocket添加安全防护,仅允许指定域名访问
针对你用ws模块搭建WebSocket服务,想要限制只有自己的mydomain.com域名能连接并读取数据的需求,我整理了几个实用的方案,结合你的代码来具体说明:
1. 检查Origin请求头(基础防护)
浏览器发起WebSocket连接时,会自动带上Origin请求头,标识请求来自哪个域名。我们可以在服务端验证这个头,只允许指定域名的请求建立连接。
修改你的服务端代码:
var WebSocketServer = require('ws').Server; wss = new WebSocketServer({ port: 8000 }); wss.on('connection', function (ws, req) { // 获取请求头里的Origin const origin = req.headers.origin; // 允许的域名列表,这里只放你的域名 const allowedOrigins = ['https://mydomain.com']; // 验证Origin是否在允许列表里 if (!allowedOrigins.includes(origin)) { ws.close(403, 'Forbidden: Unauthorized origin'); return; } // 后续正常的连接处理逻辑 ws.on('message', function(message) { console.log('Received:', message); }); });
⚠️ 注意:这个方法只能防普通浏览器请求,恶意客户端可以伪造Origin头绕过,所以只能作为基础防护,不能单独依赖。
2. 使用API密钥/令牌验证(更可靠)
可以在客户端连接时带上一个预定义的密钥,服务端验证通过后才允许建立连接。
服务端修改:
var WebSocketServer = require('ws').Server; wss = new WebSocketServer({ port: 8000 }); const VALID_API_KEY = 'your-secret-api-key-here'; // 自己设置一个安全的密钥 wss.on('connection', function (ws, req) { // 从URL参数里获取API密钥 const urlParams = new URLSearchParams(req.url.slice(1)); const apiKey = urlParams.get('apiKey'); if (!apiKey || apiKey !== VALID_API_KEY) { ws.close(403, 'Forbidden: Invalid API key'); return; } // 验证通过后的逻辑 });
客户端修改:
// 连接时带上API密钥参数 var wss = new WebSocket('wss://mydomain.com?apiKey=your-secret-api-key-here'); wss.onmessage = function(e) { var data = JSON.parse(e.data); // 处理数据 };
建议把密钥存在客户端的环境变量或者安全的存储里,不要硬编码在公开的代码中(比如可以通过后端渲染页面时注入)。
3. 结合HTTP会话验证(如果网站有用户登录)
如果你的网站已经有用户登录系统,可以利用已有的HTTP会话来验证WebSocket连接。比如用户登录后会有一个会话ID存在Cookie里,WebSocket连接时会自动带上Cookie,服务端可以验证这个会话是否有效。
服务端示例(假设用express-session):
const express = require('express'); const session = require('express-session'); const WebSocketServer = require('ws').Server; const app = express(); // 配置session app.use(session({ secret: 'your-session-secret', resave: false, saveUninitialized: true })); // 先启动HTTP服务器,再挂载WebSocket const server = app.listen(8000); const wss = new WebSocketServer({ server }); wss.on('connection', function (ws, req) { // 利用express-session的中间件解析Cookie里的会话 session({ secret: 'your-session-secret', resave: false, saveUninitialized: true })(req, {}, () => { // 检查会话是否有效,比如是否有用户信息 if (!req.session.user) { ws.close(403, 'Forbidden: Not authenticated'); return; } // 验证通过后的逻辑 }); });
这种方式适合有用户体系的网站,能确保只有登录后的用户(且来自你的域名)才能连接。
4. 启用WSS(WebSocket Secure)
一定要用wss://而不是ws://,也就是通过HTTPS来传输WebSocket数据。WSS会加密传输的数据,防止中间方窃听或篡改,同时也能让浏览器更严格地验证Origin(非加密的ws可能被某些浏览器忽略Origin验证)。
你需要在服务端配置SSL证书,修改WebSocket服务器的创建代码:
const fs = require('fs'); const WebSocketServer = require('ws').Server; const serverOptions = { cert: fs.readFileSync('/path/to/your/cert.pem'), key: fs.readFileSync('/path/to/your/private-key.pem') }; // 创建HTTPS服务器,再挂载WebSocket const httpsServer = require('https').createServer(serverOptions); const wss = new WebSocketServer({ server: httpsServer }); httpsServer.listen(8000);
总结
- 基础防护用Origin验证,快速实现但有局限性;
- 更可靠的用API密钥或会话验证;
- 必须启用WSS来加密传输,防止数据被窃听。
内容的提问来源于stack exchange,提问作者ToneCat
相关产品推荐
相关产品推荐

