HTTPS
HTTPS为标准HTTP协议增加了TLS的安全性,在Node中HTTPS被实现为一个有别于HTTP的独立模块,除了一些小差别,别的都很相似。
HTTPS核心模块扩展了HTTP模块,并将tls模块作为传输机制。例如,https.Server
伪类继承自http.Server
伪类。
首先需要创建私钥和自签名证书,这和上一篇中的做法相同
本篇略有缩减,如有理解困难或细节疑问请配合前置文章学习
一、构建安全的HTTP服务器
1.1 设置服务器选项并创建服务器
const https = require('https');
const options = {
key: fs.readFileSync('...'),
cert: fs.readFileSync('...')
}
const server = https.createServer(options, function(req,res){
res.writeHead(200, {
'Content-Type': 'text/plain'
})
res.end('hello');
})
1.2 监听连接
server.listen(port);
listen命令是异步的,这意味着服务器不会在接收该命令后立刻监听连接。但是可以提供一个回调函数,回调会在开始监听的时候立刻被调用。
1.3 验证HTTPS客户端证书
可以通过指定服务器的一些启动选项来验证客户端的真实性:
const options = {
key: ...,
cert: ...,
requestCert: true, // 要求客户端发送证书
rejectUnauthorized: true // 要求服务器拒绝未通过认证的请求
}
如果忽略了最后要求拒绝选项,仍然可以通过查看客户端流上的authorized属性来进行操作:
server.on('request', (req, res) => {
console.log(req.socket.authorized);
})
也可以获取客户端证书,但是只可以在socket.authorized为true时才能保证证书的真实性:
console.log(req.socket.getPeerCertificate());
二、创建HTTPS客户端
Node中创建HTTPS请求和创建HTTP请求非常类似,实际上可能就是相同的,因为并不需要传入客户端私钥或者客户端证书,除非服务端需要客户端提供。
2.1 初始化
const https = require('https');
const options = {
host: '127.0.0.1',
port: 1234,
method: 'get',
path: '/'
}
需要创建一个配置对象,包含端口号、请求方式等内容。
2.2 创建请求
const request = https.request(options, (res) => {
res.on('data', () => {
...
})
})
request.write('hello');
request.end();
创建的客户端的请求是一个可写流,可以向其中写入数据,或者将一个可读流传入其中。
一旦接受到来自服务器的响应,就会触发回调,通过回调接受到的可读流对象,你可以拿到响应的一些细节。
2.3 验证HTTPS服务器证书
除了信道安全之外,客户端对服务器证书的验证是网络上使用HTTPS最常见的理由。大多数网络浏览器希望确保与他们交互的服务器与URL栏中显示的一致。
进行请求之后,获得res对象,在其socket属性内有一个stream对象,他是TLS流,因此可以调用stream.getPeerCertificate()
来获取服务器证书。
打印证书,通过证书信息和res.socket.authorized为true,你可以判断是否匹配。