websocket,如何更换为使用证书的wss安全协议?
发布于 作者:苏南大叔 来源:程序如此灵动~
websocket
协议是建立在TCP
连接上的全双工通信协议,而HTTP
是基于请求-响应模式的。websocket
协议是双向的,而Http
协议是单向的。ws
和wss
的关系,就像http
和https
的关系。本文要讨论的就是:websocket
的ws
协议,如何升级为安全的wss
协议。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10
,nodejs@20.18.0
,ws@8.18.0
。当然,服务器端并不是仅仅只可以使用nodejs
,其它的高级编程语言也是可以的。node
仅仅是本文的龙套演示语言而已。
前文回顾
在前面的文章里面,websocket
的使用问题,分为两个部分讲解,分别是服务器端和客户端两部分。
服务器端都可以发送和接收消息,但是只有服务器端可以主动发送.ping()
操作,客户端的.pong()
操作是被动的。
具体参考文章:
上面两篇文章里的范例,都是使用默认的ws
协议的,也就是不加密的版本。接下来的代码里面,将演示如何把ws
协议升级为wss
安全协议。
获取证书
“安全”通信的前提,就是证书,或者说一个公钥和密钥的组合。公钥和密钥都部署在服务器上,而同时对于自签名的证书,需要浏览器客户端对自签名的证书(公钥)进行信任设置。
获取证书的方式很多,并不一定要本段内容的方法。这里使用最简单的方式获得了一个本地localhost
的证书:
mkcert localhost 127.0.0.1 ::1
注意:没写端口号。
获得的证书共两个文件,*key.pem
是私钥,另外一个是公钥。
参考文章:
使用 https内置模块
在nodejs
的世界里面,是使用nodejs
内置默认的https
模块,来对ws
进行包装的,进而提升为wss
协议。
const https = require('https');
const fs = require('fs');
const server = https.createServer({
cert: fs.readFileSync('./cert/cert.pem'), // 公钥文件
key: fs.readFileSync('./cert/cert-key.pem') // 私钥文件
});
server.listen(8080, () => {
console.log('WebSocket server is running on wss://localhost:%s', server.address().port);
});
const WebSocket = require('ws');
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
console.log('received: %s', message);
ws.send('Hello from server');
});
});
代码对比
普通的ws
服务器:
const WebSocket = require('ws');
let wss = new WebSocket.Server({ port: 8080 }, () => {
console.log('WebSocket server is running on ws://localhost:%s', wss.options.port);
});
//...
ws
附在普通的http
模块下:
let http = require("http");
let httpServer = http.createServer();
httpServer.listen(81, () => console.log('http://localhost:%s', httpServer.address().port));
const WebSocket = require('ws');
let wss = new WebSocket.Server({ server: httpServer });
console.log('ws://localhost:%s', httpServer.address().port);
// ...
使用证书安全设置的wss
服务器:
let https = require('https');
let fs = require('fs');
let httpsServer = https.createServer({
key: fs.readFileSync('./cert/cert-key.pem'),
cert: fs.readFileSync('./cert/cert.pem')
}, );
httpsServer.listen(82, () => console.log('https://localhost:%s', httpsServer.address().port));
const WebSocket = require('ws');
let wss = new WebSocket.Server({ server: httpsServer });
console.log('wss://localhost:%s', httpsServer.address().port);
//...
也就是说:nodejs
自带的https
模块,初始化了证书设置,然后把自己传递到WebSocket.Server()
中,使用server
参数代替了port
参数。
因此,在代码的最后,也由这个https
的server
去监听端口。(原来是由ws
自己监听的)。
执行代码对比的方式,可以参考:
结语
更多socket
文章,请点击苏南大叔的博客文章:


