node https 双向认证
本博客结合一下连接
https://www.cnblogs.com/wzs5800/p/12778904.html.
https://www.cnblogs.com/wzs5800/p/12779223.html
https://www.cnblogs.com/mhc-fly/p/8472972.html
一、生成证书
使用cfssl工具: 工具下载地址
CA证书
1.准备ca-config.json(根证书配置文件)
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
ca-csr.json(根证书请求配置文件)
注意:
因为自签证书,ca-csr配置里的CN不要以"www"开头,测试过www开头会导致通信失败。
{
"CN": "MYCA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Guangzhou",
"L": "Guangzhou",
"O": "组织",
"OU": "部门"
}
]
}
生成CA证书
cfssl.exe gencert -initca ca-csr.json | cfssljson.exe -bare ca -
服务端证书
server-csr.json
hosts为服务端的IP,请根据需要自行补充。
{
"CN": "my-server",
"hosts": [
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Guangzhou",
"L": "Guangzhou",
"O": "组织",
"OU": "部门"
}
]
}
生成服务端证书
cfssl.exe gencert -ca=ca.pem\
-ca-key=ca-key.pem\
-config=ca-config.json\
-profile=server server-csr.json | cfssljson.exe -bare server
客户端证书
客户端证书和服务端证书生成步骤一样,只不过不需要配置host字段。
client-csr.json
{
"CN": "my-client",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Guangzhou",
"L": "Guangzhou",
"O": "组织",
"OU": "部门"
}
]
}
生成客户端证书
cfssl.exe gencert -ca=ca.pem\
-ca-key=ca-key.pem\
-config=ca-config.json\
-profile=client client-csr.json | cfssljson.exe -bare client
最后会生成以下证书目录如下
├── ca.csr
├── ca.pem
├── ca-key.pem
├── client.csr
├── client.pem
├── client-key.pem
├── server.csr
├── server.pem
├── server-key.pem
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt //生成ca.crt openssl x509 -req -CA ca.crt -CAkey ca-key.pem -CAcreateserial -in server.csr -out server.crt //生成server.crt openssl x509 -req -CA ca.crt -CAkey ca-key.pem -CAcreateserial -in client.csr -out client.crt //生成client.crt
二、Node代码
服务端
const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('./certificate/server-key.pem'), cert: fs.readFileSync('./certificate/server.pem'), ca: [fs.readFileSync('./certificate/ca.pem')], // 使用客户端证书验证 requestCert: true, // 如果没有请求到客户端来自信任CA颁发的证书,拒绝客户端的连接 rejectUnauthorized: true }; const port = 8081; https.createServer(options, (req, res) => { console.log('server connected', res.connection.authorized ? 'authorized' : 'unauthorized'); res.writeHead(200); res.end('hello world!\n'); }).listen(port, () => { console.log(`running server https://127.0.0.1:${port}`) });
客户端
const https = require('https'); const fs = require('fs'); const options = { hostname: '127.0.0.1', port: 8081, path: '/', method: 'GET', key: fs.readFileSync('./certificate/client-key.pem'), cert: fs.readFileSync('./certificate/client.pem'), ca: [fs.readFileSync('./certificate/ca.pem')], agent: false, // 开启双向认证 rejectUnauthorized: true }; // options.agent = new https.Agent(options); const req = https.request(options, (res) => { console.log('client connected', res.connection.authorized ? 'authorized' : 'unauthorized'); console.log('状态码:', res.statusCode); res.setEncoding('utf-8'); res.on('data', (d) => { process.stdout.write(d); }); }); req.on('error', (e) => { console.error(e); }); req.end();
三、火狐浏览器证书生成
首先 不能在火狐里对要访问的网址添加例外
打开 选项->高级->查看证书->证书机构->导入。先择服务端ca.crt后根据提示导入证书
生成p12文件
openssl pkcs12 -export -clcerts -in client.crt -inkey client-key.pem -out client.p12
密码随便输入
火狐浏览器 打开 选项->高级->查看证书->您的证书->导入 p12 文件, 输入上边设置的密码