借助mkcert签发本地证书

mkcert 是由 Filippo Valsorda 使用go语言开源的一款零配置搭建本地证书服务的工具,它可以兼容Window, Linux, macOS等多种开发平台,省去了我们自签本地证书的繁琐步骤,从而让我们专注于开发。

1. 安装mkcert

1.1 Windows

Windows环境下,推荐使用Chocolatey包管理工具安装mkcert,你可以选择使用cmdpower shell安装Chocolatey

以管理员权限打开cmd窗口,输入以下命令进行安装

1
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

以管理员权限打开power shell窗口,输入以下命令进行安装

1
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Chocolatey安装完成之后,命令行窗口输入以下命令安装mkcert

1
choco install mkcert

1.2 Linux

以下假定使用的是全新的Linux系统!

首先更新软件源,防止E: Unable to locate package的错误,

1
sudo apt update

首先安装证书数据库工具certutil:

1
2
sudo apt install libnss3-tools // ubuntu
sudo yum install nss-tools // centos

然后,安装包管理工具Linuxbrew:

1
2
sudo apt install linuxbrew-wrapper  // ubuntu
sudo yum install linuxbrew-wrapper // centos 待定

最后,使用brew安装mkcert

1
brew install mkcert

tips:可能需要执行两次命令,同时不要使用sudo命令,系统会提示你不要使用root权限来执行brew

mkcert安装目录下启动mkcert,推荐将mkcert加入全局命令,

1
PATH=$PATH:/home/linuxbrew/.linuxbrew/Cellar/mkcert/1.2.0/bin

1.3 macOS

使用Homebrew安装mkcert

1
2
brew install mkcert
brew install nss # if you use Firefox

2. 生成本地CA证书

2.1 生成根证书

mkcert安装完成之后就可以使用mkcert命令生成本地CA证书了,非常简单,傻瓜式安装。

首先,生成根证书,一般在C:\Users\用户名\AppData\Local\mkcert目录下会生成rootCA.pemrootCA-key.pem两个文件。

根证书用来充当第三方证书签发机构,类似于Symantec这种机构,为网站签发CA证书。因为证书也可以伪造,所以浏览器需要验证证书的有效性,证书有效之后才可以进行https连接,而第三方签发机构提供证书的可信度验证。

rootCA文件就是告诉浏览器我们自签的证书是真实有效的,接下来我们签发的本地证书都离不开rootCA

1
2
3
4
$ mkcert -install
Created a new local CA at "/Users/filippo/Library/Application Support/mkcert" ?
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires restart)! ?

2.2 签发本地证书

根证书生成之后就可以签发本地证书了,命令超级简单,唯一需要注意的就是生成的证书存放路径就是命令的执行路径。

1
2
3
4
5
6
7
8
9
10
11
12
$ mkcert example.com "*.example.org" myapp.dev localhost 127.0.0.1 ::1
Using the local CA at "/Users/filippo/Library/Application Support/mkcert"

Created a new certificate valid for the following names ?
 - "example.com"
 - "*.example.org"
 - "myapp.dev"
 - "localhost"
 - "127.0.0.1"
 - "::1"

The certificate is at "./example.com+5.pem" and the key at "./example.com+5-key.pem"

2.3 root stores

mkcert支持以下根存储(mkcert supports the following root stores:):

  • macOS system store
  • Windows system store
  • Linux variants that provide either
    • update-ca-trust (Fedora, RHEL, CentOS) or
    • update-ca-certificates (Ubuntu, Debian) or
    • trust (Arch)
  • Firefox (macOS and Linux only)
  • Chrome and Chromium
  • Java (when JAVA_HOME is set)

这句话的意思就是说,mkcert会自动把证书加入系统认证,操作系统和浏览器可以直接识别。比如,证书安装完成之后chrome的证书信任中心会增加以下内容:

2.4 node环境验证

node不会使用root store,因此需要特殊对待,命令行手动设置NODE_EXTRA_CA_CERTS这个环境变量。

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

** mkcert -CAROOT会输出本地根证书的存储路径,可以使用环境变量$CAROOT来指定寻找证书的默认路径。

使用node开启https服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var https = require('https');
var fs = require('fs');

const hostname = '127.0.0.1';
const port = 3000;

var options = {
    key : fs.readFileSync('c:/证书路径'),
    cert : fs.readFileSync('c:/证书路径'),
}

const server = https.createServer(options ,(req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});

server.listen(port, hostname, () => {
    console.log(`Server running at https://${hostname}:${port}/`);
});

https进行访问:

3. 分享

搞定了自己,接下来就要搞定别人,如何让其它用户也识别我们的本地证书呢?

mkcert同样也给我们提供了可移植的解决方案。

将自签证书(包括公钥和私钥)以及根证书的公钥拷贝给其它用户,修改$CAROOT环境变量,指定mkcert寻找根证书的路径,

linux系统下:

1
export CAROOT="/home/..."

window系统下:

设置系统的环境变量,变量名为CAROOT

我的电脑->属性->高级系统设置->环境变量

最后执行mkcert -install即可,控制台会提示,此时我们的自签证书就可以在其它机器上运行了,根证书被导入到了浏览器的证书信任中心。

1
2
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox and/or Chrome/Chromium trust store (requires browser restart)! ?

发表回复