Nest + Vue3 下如何配置本地HTTPS

904 阅读3分钟

大部分项目在开发时并不介意是否采用安全连接,所以关于此类的应用和介绍并不多。但是对于一些有较高安全性要求的项目会对此有硬性要求。例如,开发微软的Office插件(Addin)或者一些WebRTC项目,需要拾取浏览器的音频视频接口。本文就此需求进行些许探索,记录在Nest后端(Express5框架)加Vue3前端(Vite脚手架)下如何配置本地HTTPS安全连接。

整个过程大致分为四个步骤:下载工具、配置根证书、生成域名证书和将域名证书加载到应用程序中。

下载和安装mkcert

来与FiloSottile的优秀项目,在GitHub上有3.5万星(2020-06),代码主要功能是生成并注册根证书和一键创建指定域名证书。

安装

直接下载

脚本(命令)安装

macOS使用Homebrew安装

brew install mkcert
brew install nss # 如果需要在火狐浏览器下调试

Windows Chocolatey或Scoop

choco install mkcert
# or
scoop bucket add extras
scoop install mkcert

Linux安装

# 必要组件
sudo apt install libnss3-tools

brew install mkcert
# or 手动下载
curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64"
chmod +x mkcert-v*-linux-amd64
sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert

注意:有相当一部分开发者使用的开发环境是Windows+WSL2。这就相当于是有两个操作系统,那么默认的一件安装只会安装在当前系统中,另外一个系统(无论Windows还是WSL)都需要手动添加根证书。

配置根证书

如果只是在“单纯”的Linux或者MacOS环境中,那么只需要执行命令mkcert --install,便会在~/.local/share/mkcert目录中产生根证书rootCA-key.pemrootCA.pem根证书文件。

windows+wsl环境中,建议在linux子系统中安装mkcert,并自动注册到系统中。然后通过mmc手动添加到系统中。

  1. 运行mmc.exe
  2. “文件” > “添加、删除管理单元”
  3. 在对话框中的左侧“可用的管理单元”中找到“证书”,选择添加
  4. 弹出的对话框中选择“我的用户账户”(默认)或“计算机账户”,点“完成”,点“确定”
  5. 展开“控制台根节点” > “证书” > “收信人的根证书颁发机构”
  6. 点右键 > “所有任务” > “导入” > “下一步”
  7. 打开WSL中根证书所在目录,例如\\wsl.ocalhost\Ubuntu-20.04\home\django\.local\share\mkcert,文件类型选择所有文件,选择rootCA.pem,并下一步。选择“自动选择证书类型”

如果是苹果系统或Linux系统,将环境变量添加到配置中,这样Node系统的https才能根据指定根证书验证域名证书。

export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"

如果没有这个步骤,NodeJS的应用程序会报告Error: unable to verify the first certificate错误。

生成域名证书

在正在开发的应用程序根目录下,运行:

mkcert 127.0.0.1 localhost

成功后,会生成两个文件localhost+1-key.pemlocalhost+1.pem两个文件,说明HTTPS的证书已经生成好。

应用程序中加载证书

NestJS

在NestJS的启动程序 /src/main.ts 文件中加入选项

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { readFileSync } from 'fs';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule, {
    // ...
    httpsOptions: {
      key: readFileSync(resolve(join(__dirname,'../../localhost+1-key.pem'))),
      cert: readFileSync(resolve(join(__dirname,'../../localhost+1.pem'))),
    },
  });
  // ***
}
bootstrap();

此时,无论是打开127.0.0.1 还是 localhost,浏览器都会显示是安全域名。当然,如果还需要绑定其他地址也是可以的,不过本人觉得意义不大。因为作为网络访问,那么所有访问者的电脑上都要安装指定的根证书,略显麻烦。

Vue3(vite脚手架)

为了尽量保持与生产环境的一致性以及开发的便利性,前端应用程序采用HMR和API代理。这里我们需要修改vite.config.js文件实现证书加载

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { readFileSync } from 'fs';
import { join, resolve } from 'path';
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  server: {
    host: '0.0.0.0',
    port: 8080,
    open: 'https://127.0.0.1:8080',
    https: {
      key: readFileSync(resolve(join(__dirname,'../localhost+1-key.pem'))),
      cert: readFileSync(resolve(join(__dirname,'../localhost+1.pem'))),
    },
    proxy: {
      '/api': {
        target: 'https://127.0.0.1:3000',
        changeOrigin: true,
      },
    },
  },
});

如果一切配置正确,最后用https方式打开程序网站是这样

Screenshot from 2022-06-25 16-09-20.png