大部分项目在开发时并不介意是否采用安全连接,所以关于此类的应用和介绍并不多。但是对于一些有较高安全性要求的项目会对此有硬性要求。例如,开发微软的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.pem
和rootCA.pem
根证书文件。
windows+wsl环境中,建议在linux子系统中安装mkcert,并自动注册到系统中。然后通过mmc手动添加到系统中。
- 运行mmc.exe
- “文件” > “添加、删除管理单元”
- 在对话框中的左侧“可用的管理单元”中找到“证书”,选择添加
- 弹出的对话框中选择“我的用户账户”(默认)或“计算机账户”,点“完成”,点“确定”
- 展开“控制台根节点” > “证书” > “收信人的根证书颁发机构”
- 点右键 > “所有任务” > “导入” > “下一步”
- 打开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.pem
和localhost+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
方式打开程序网站是这样