【原创】NodeJs 搭建https服务

1、http、https、http2的关系

http:目前绝大多数是http1.1版本,最原始的web协议,默认80端口,基于TCP协议。
https:加密的http协议(http+SSL/TLS),默认443端口,基于TCP协议。
http2:第二代http协议,相较于HTTP1.x,大幅度的提升了web性能。在与HTTP/1.1完全语义兼容的基础上,进一步减少了网络延迟和传输的安全性,基于TCP协议。

2、HTTPS服务

2.1 自建CA

// 1.生成CA私匙,des3代表加密算法,还可以选择aes256等
openssl genrsa -des3 -out ica.key 1024
// 2.生成CA证书请求
openssl req -new -key ica.key -out ssl.csr
// 3.生成CA根证书
openssl x509 -req -in ica.csr -extensions v3_ca -signkey ica.key -out ica.crt

2.2 server端证书

如果用户想得到一份属于自己的证书,他应先向 CA 提出申请。在 CA 判明申请者的网站信息后,便为他分配一个公钥,并且 CA 将该公钥与申请者的身份信息绑在一起,并为之签字后,便形成证书发给申请者。自建CA生成的如下server.crt并不能让服务器信任,实际开发中是第三方CA证书管理机构(付费的,可以理解为他们自建的CA被浏览器开发者添加到了可信任的证书颁发机构列表中)签发证书给申请者,浏览器才信任。但是咱们可以把自建的CA证书添加到浏览器可信任列表中,具体见本文2.5。

// 1.生成server私匙
openssl genrsa -out server.key 1028
// 2.生成server证书请求
openssl req -new -key server.key -out server.csr
// 3.生成server证书
openssl x509 -days 365 -req -in server.csr -extensions  v3_req -CAkey ica.key -CA ica.crt -CAcreateserial -out server.crt  -extfile openssl.cnf

说明:
openssl.cnf文件内容

[req]  
    distinguished_name = req_distinguished_name  
    req_extensions = v3_req  

    [req_distinguished_name]  
    countryName = CN 
    countryName_default = CN  
    stateOrProvinceName = Beijing  
    stateOrProvinceName_default = Beijing  
    localityName = Beijing 
    localityName_default = Beijing
    organizationalUnitName  = HD
    organizationalUnitName_default  = HD
    commonName = localhost  
    commonName_max  = 64  

    [ v3_req ]  
    # Extensions to add to a certificate request  
    basicConstraints = CA:FALSE  
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment  
    subjectAltName = @alt_names  

    [alt_names]  
   #注意这个IP.1的设置,IP地址需要和你的服务器的监听地址一样 DNS为server网址,可设置多个ip和dns
    IP.1 = 127.0.0.1
    DNS.1 = localhost

2.3 node.js搭建https服务器

//使用nodejs自带的http、https模块
const https = require('https');
const http = require('http');
const fs = require('fs');
const path = require('path');
const koa = require('koa');
const app = new koa();

app.on('error', (error, ctx) => {
    console.log('something error ' + JSON.stringify(ctx.onerror));
});

app.use(async ctx => {
    ctx.body = `This is ${ctx.protocol} visit`;
});

//根据项目的路径导入生成的证书文件
const privateKey  = fs.readFileSync(path.join(__dirname, './certificate/server.key'), 'utf8');
const certificate = fs.readFileSync(path.join(__dirname, './certificate/server.crt'), 'utf8');
const credentials = {key: privateKey, cert: certificate};

//创建http与HTTPS服务器
const httpServer = http.createServer(app.callback());
const httpsServer = https.createServer(credentials, app.callback());

//可以分别设置http、https的访问端口号
const PORT = 8000;
const SSLPORT = 8001;

//创建http服务器
httpServer.listen(PORT, function() {
    console.log('HTTP Server is running on: http://localhost:%s', PORT);
});

//创建https服务器
httpsServer.listen(SSLPORT, function() {
    console.log('HTTPS Server is running on: https://localhost:%s', SSLPORT);
});

2.4 nginx配置https

server {
        listen       80;
        server_name  localhost;
        rewrite ^ https://$http_host$request_uri? permanent;   
        # force redirect http to https
    }
server {
       listen       443 ssl;
        server_name  localhost;
        ssl_certificate      server.crt;
        ssl_certificate_key  server.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

       location / {
            root   D:\myProjects\hmall-pc\src\main\webapp;
            try_files $uri $uri/ @router;
            index hmall-base.html;
        }
    }

2.5 消除浏览器安全警告

因为我们不是官方的CA机构并没有内置在浏览器或系统中,所以浏览器会认为该CA非法,此时我们需要将我们自建CA的根证书(ica.crt)加入到浏览器中。
Chrome :设置-设置-设置-高级-隐私设置和安全性-管理证书-导入
火狐:设置-选项-隐私与安全-证书-查看证书-证书机构-导入
亲测火狐导入之后有效,chrome的依然有安全警告...


火狐添加ica.crt之后

3、加密方式

3.1 对称加密

  • 对称加密:加密和解密用同一个秘钥的加密,特点是快。


    对称加密
  • 对称加密的算法存在的问题:
    多个客户端的时候,在一端生成一个秘钥,传输秘钥的过程,如果被中间人拦截,秘钥也会被获取。


    多用户对称加密

3.2 非对称加密

  • 非对称加密:会有一对秘钥公钥和私钥,公钥加密,私钥解密,特点是安全,但是慢。


    非对称加密
  • 非对称加密存在的问题:
    私钥只保存在服务器端,公钥可以发送给所有的客户端。在传输公钥的过程中,有被中间人获取的风险,虽然中间人是无法破解(因为私钥只保存在服务器端,只有私钥可以破解公钥加密的内容),但是公钥被中间人拿到可篡改。


    Man-in-the-MiddleAttack篡改公钥

    如果中间人篡改公钥,客户端和服务器端相互传递的消息容易都是假的。

3.3 第三方认证

  • 公钥被掉包,是因为客户端无法分辨传回公钥的到底是中间人,还是服务器。在HTTPS中,使用 数字证书(网站信息 + 数字签名)来解决这个问题,中间人拦截后把服务器的公钥替换为自己的公钥,因为数字签名的存在,会导致客户端验证签名不匹配,这样就防止了中间人替换公钥的问题。
    数字签名:将网站的信息加密后通过第三方机构的私钥再次进行加密,生成数字签名。
    第三方证书

4、https工作机制

https工作机制
  • client使用公钥A给秘钥X加密,server使用私钥B给秘钥X解密,这一过程是非对称加密。
  • client和server利用对称加密秘钥X的快捷性来加密解密报文

参考文章:
https://blog.csdn.net/m0_37263637/article/details/80314093
https://www.kuacg.com/22672.html
https://www.jianshu.com/p/b92d4c8cbe05

你可能感兴趣的:(【原创】NodeJs 搭建https服务)