什么时候我们需要在本地使用HTTPS?
问题
在大多数情况下,我们在本地开发应用时不需要HTTPS。但是,如果你的应用需要与第三方进行身份验证, 或者需要监听来自其他应用的webhooks...而这些第三方要求你的应用必须使用HTTPS才能接收他们的请求,那该怎么办呢?
当然,在生产环境中会使用HTTPS,但如何在本地开发应用时建立安全连接呢?
我们有几个选择,比如使用PageKite或ngrok来创建指向你的localhost的HTTPS隧道, 但这些服务有一些缺点:
免费计划中可同时使用的隧道/请求数量有限。
无法使用特定的域名,每次开发应用时都会不同,我们必须重新配置应用的环境变量。
而且它们非常慢 ,这会浪费大量开发/测试应用的时间。
如果你遇到类似的问题,这里有解决方案
解决方案
这里的解决方案是使用OpenSSL生成SSL证书,并使用这些证书创建HTTPS服务器。
生成根SSL证书
首先,我们需要创建一个根SSL证书来签署我们将用于localhost的任何证书。
使用以下命令创建一个key
,用于在下一步生成根SSL证书:
openssl genrsa -des3 -out rootCA.key 2048

系统会要求你输入一个密码短语来生成密钥,只需输入一个随机字符串并验证即可。
请记住这个密码短语,因为在接下来的步骤中还会用到!
生成的密钥将保存在rootCA.key
文件中,使用以下命令用它来生成根SSL证书:
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 7300 -out rootCA.pem

填写所需信息(**密码短语**必须与第一步生成`rootCA.key`时使用的密码相匹配!)
此证书将保存在`rootCA.pem`文件中。
### <Twemoji emoji="keycap-2" /> 信任根SSL证书
要使用**根SSL证书**生成的证书,我们需要告诉操作系统信任这个**根证书**。
打开**钥匙串访问**应用程序(MacOS),选择**证书**标签:

通过拖拽或导航到**文件 / 导入项目...**来导入`rootCA.pem`。
然后在导入的证书上**右键点击 / 显示简介**(或**双击**)

展开**信任**标签,在第一个设置中选择**始终信任**,然后保存。
**钥匙串访问**随后会显示类似**"此证书被标记为此帐户信任"**的消息,这意味着你已成功信任了**根SSL证书** <Twemoji emoji="party-popper" />。
### <Twemoji emoji="keycap-3" /> 创建本地SSL证书
现在,我们将使用已信任的**根SSL证书**来生成用于**localhost**的**SSL证书**。
#### 第1步
创建一个名为`server.csr.cnf`的配置文件,内容如下。**OpenSSL**将使用此文件生成**证书密钥**:
```bash:server.csr.cnf showLineNumbers
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=US
ST=RandomState
L=RandomCity
O=RandomOrganization
OU=RandomOrganizationUnit
emailAddress=hello@example.com
CN = localhost
使用上述配置创建证书密钥并保存到server.key
文件:
let Koa = require('koa');
let app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
module.exports = app
在你的应用中创建一个名为 certs/
的目录,然后将 server.key
和 server.crt
移动到该目录中。
使用 https
模块加载证书文件并创建 HTTPS 服务器:
let app = require('./server')
let https = require('https')
let fs = require('fs')
let path = require('path')
let certOptions = null
try {
certOptions = {
key: fs.readFileSync(path.resolve('certs/server.key')),
cert: fs.readFileSync(path.resolve('certs/server.crt'))
}
} catch(err) {
console.log('No certificate files found!')
}
let host = process.env.APP_URL || 'localhost'
let isLocal = host === 'localhost'
let enableHTTPSInLocal = Boolean(isLocal && certOptions)
let port = enableHTTPSInLocal ? 443 : process.env.PORT || 3434
let protocol = (isLocal && !certOptions) ? "http" : "https"
let url = `${protocol}://${host}${isLocal ? `:${port}` : ''}`
let callback = () => {
console.log(`App start successfully at ${url}`)
}
if (enableHTTPSInLocal) {
https
.createServer(certOptions || {}, app.callback())
.listen(port, callback)
} else {
app.listen(port, callback)
}
项目结构应该如下所示:

使用 npm start
启动你的应用 ( 注意是运行 node index.js
, 而不是 node server.js
!)

如果没有证书文件存在,应用将以普通的 http
方式启动。

当你把证书文件放进去后,应用将以 https 方式在 443 端口启动。

在浏览器中打开 https://localhost:443
,你就能看到你的应用通过 HTTPS 运行了
源代码可以在这个仓库中找到。
总结
如果你不是 Node.js 开发者,你可以搜索如何在你喜欢的技术栈中使用证书文件创建 HTTPS 服务器
希望这个指南能帮助你在本地使用 HTTPS 开发应用!
分享快乐