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是私钥,另外一个是公钥。

获取证书的方式很多,并不一定非要使用本段内容提供的mkcert方法。参考文章:
使用 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文章,请点击苏南大叔的博客文章: