背景
iOS WebView 中打开本地页面竟然白屏,最后发现是只支持 HTTPS。于是研究了一下前端本地环境怎么配置 HTTPS。
技术:Vite + Vue
mkcert
要想是完成 HTTPS 的配置,就要在本地开发服务器上设置 SSL 证书。
提到安装证书必然就是 mkcert。mkcert 是一个用 GO 写的零配置专门用来本地环境 https 证书生成的工具。
安装 mkcert 工具
但是 Windows 下安装似乎有点麻烦,官网下载:github.com/FiloSottile… ,mkcert-v1.4.4-windows-amd64.exe
,不需要运行。
创建本地 CA
将 exe 文件拖入在命令行中,加上 -install
回车安装。
也就是相当于执行:mkcert -install
。
mkcert 会自动将其安装到系统信任存储中,这样由它签发的证书就会被系统信任。
生成 SSL 证书
mkcert 127.0.0.1 #创建IP证书
mkcert xxx.com #或创建域名证书
需要指定想要证书支持的域名,对于本地开发,通常是 localhost 或者本地 IP。执行完成后会在在当前目录生成 {ip或域名}-key.pem
、{ip或域名}.pem
文件。一个是证书文件,一个是私钥文件。
前端项目中使用
以上 mkcert 部分介绍了一般使用 mkcert 生成证书的方法。对于前端项目还需要配置开发服务器使用 SSL 证书。
在 Webpack 中使用
module.exports = {
devServer: {
https: true,
key: fs.readFileSync('path/127.0.0.1-key.pem'),
cert: fs.readFileSync('path/127.0.0.1.pem')
}
};
在 Node.js 中使用
const https = require('node:https');
const fs = require('node:fs');
const options = {
key: fs.readFileSync('path/127.0.0.1-key.pem'),
cert: fs.readFileSync('path/127.0.0.1.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
在 Vite 中使用
直接使用
server: {
https: {
key: fs.readFileSync('C:/Users/choreau/127.0.0.1-key.pem'),
cert: fs.readFileSync('C:/Users/choreau/127.0.0.1.pem'),
},
host: '0.0.0.0',
port: 5173,
},
使用插件 @vitejs/plugin-basic-ssl
Vite 官网推荐使用 @vitejs/plugin-basic-ssl。
Vite 配置:
// vite.config.ts
import basicSsl from '@vitejs/plugin-basic-ssl'
export default defineConfig({
plugins: [
basicSsl()
]
})
使用这个插件,会自动创建签名证书,但是浏览器报错:您的连接不是私密连接。需要手动信任。
不推荐使用。
使用插件 vite-plugin-mkcert
使用这个插件,浏览器不会报错。
// vite.config.ts
import mkcert from 'vite-plugin-mkcert'
export default defineConfig({
server: {
https: true
},
plugins: [mkcert()]
})
这个插件的原理是使用 mkcert 安装本地 CA
证书,并为 server.https 生成服务端证书。
所以使用这个插件也不需要单独使用 mkcert 安装根证书和 SSL 证书。
使用 http-server 启动
关于任意的静态文件,可以使用 http-server 启动服务。也支持自定义证书,启动命令也只需要一行命令。
# 可以全局安装
npm i -g http-server
# 启动服务
http-server
# 启动服务并使用自定义证书
http-server -c-1 --ssl --cert {ssl cert文件} --key {ssl key文件}
关于根证书的位置
关于根证书的位置,我在命令行中 -install 的时候,并没有显示安装的位置:
有的文章中安装截图有显示安装位置。
有的文章提到可以使用 mkcert -CAROOT
命令打印它所在的文件夹。但是因为我这里没有正常安装,mkcert 无法使用,就通过文件搜索的方式找到。
其中,后面使用 Vite 插件的方式,根证书在 /当前用户名/.vite-plugin-mkcert
文件夹下。
这个根证书 rootCA.pem
后面移动端会用到。
移动端使用
最终,Vite 项目使用的是插件 vite-plugin-mkcert
,这种方式,PC 上可以直接访问 HTTPS。因为本质上 mkcert -install
完成时会将根证书安装在 PC 上,PC 浏览器可以直接通过 HTTPS 协议访问本地 Web。但是对于移动设备需要安装根证书才能正常访问。
未信任本地证书
如果未安装根证书:
微信扫码,打开页面空白,应该是 WebView 阻止了。
浏览器中打开,会出现(以下是 Chrome):
点击高级,可以继续前往页面地址,仍然可以打开页面。
以上的表现,也跟在 PC 上使用 Vite 插件 @vitejs/plugin-basic-ssl
,浏览器或者系统未信任本地证书表现一样。
但是对于 APP WebView,页面会被阻止,所以我们需要在手机上安装根证书,使得由其签发的证书会被系统信任。
手机上安装根证书的问题
安卓,我这里暂时略过,说 iOS。
下载根证书,保存到档案中,然后“设置”中会多一个已下载文件,安装。
在给测试的手机上安装了根证书之后,iOS APP WebView 仍然打不开页面,页面空白。此时有点陷入困境,于是和各方沟通,怀疑证书问题或者 WebView 不支持 IP 的方式。(后来发现,不必要在 iOS APP 里测试呀,首先至少要在手机浏览器上能正常打开,而且也没必要用装有 APP 的测试机。)
于是先自己测试,给一台 iOS 设备发送了根域名,安装,测试。根据 www.npmjs.com/package/vit… ,也是来自 mkcert 的 README,上面说可以通过 AirDrop email http 等方式发送,我一度怀疑是通过聊天软件发送文件不行吗?
后来再反复阅读文档,github.com/FiloSottile…, 发现自己安装的过程和它好像不一样,好像并没有看到过 Certificate Trust Settings,之前想着既然安装成功就没影响吧。
然后通读了完整的 issue,以及它相关的 github.com/FiloSottile… ,最后才明白这个 issue 是在说,正常安装了证书,为什么没有出现在 Certificate Trust Settings。于是才发现还有个 证书信任设置 的设置。(顺便说下,issue 的问题是为什么安装了证书没有出现在证书信任设置中,针对 github.com/FiloSottile… 的回答,可能是由于 iOS 更新,作者并没有正确安装证书,正确的如回答中的截图)
于是解决就是去证书信任设置开启根证书信任,前往“设置”>“通用”>“关于本机”>“证书信任设置”。在“针对根证书启用完全信任”下,开启对这个证书的信任。
后来也发现其实它的 enable full trust in it 也说明了这一点,我没点进去看。
参考
- mkcert:github.com/FiloSottile…
- windows使用mkcert配置本地https环境:blog.zwying.com/archives/51…
- vite-plugin-basic-ssl:github.com/vitejs/vite…
- vite-plugin-mkcert:www.npmjs.com/package/vit…
- 使用mkcert生成自签名证书:kanchuan.com/blog/173-lo…
- Web 开发本地环境如何配置 HTTPS:juejin.cn/post/717031…
- Installed certificate does not show up in Certificate Trust Settings:github.com/FiloSottile…
- 在 iOS 和 iPadOS 中信任手动安装的证书描述文件:support.apple.com/zh-cn/10239…