如何在本地创建HTTPS服务器?

Black iphone 5 beside brown framed eyeglasses and black iphone 5 c
Published on
/7 mins read/---

什么时候我们需要在本地使用HTTPS

问题

在大多数情况下,我们在本地开发应用时不需要HTTPS。但是,如果你的应用需要与第三方进行身份验证, 或者需要监听来自其他应用的webhooks...而这些第三方要求你的应用必须使用HTTPS才能接收他们的请求,那该怎么办呢?

当然,在生产环境中会使用HTTPS,但如何在本地开发应用时建立安全连接呢?

我们有几个选择,比如使用PageKitengrok来创建指向你的localhostHTTPS隧道, 但这些服务有一些缺点:

  • 免费计划中可同时使用的隧道/请求数量有限。

  • 无法使用特定的域名,每次开发应用时都会不同,我们必须重新配置应用的环境变量。

  • 而且它们非常 ,这会浪费大量开发/测试应用的时间。

如果你遇到类似的问题,这里有解决方案

解决方案

这里的解决方案是使用OpenSSL生成SSL证书,并使用这些证书创建HTTPS服务器。

生成根SSL证书

首先,我们需要创建一个根SSL证书来签署我们将用于localhost的任何证书。

使用以下命令创建一个key,用于在下一步生成根SSL证书

openssl genrsa -des3 -out rootCA.key 2048
root-ca-key

系统会要求你输入一个密码短语来生成密钥,只需输入一个随机字符串并验证即可。

请记住这个密码短语,因为在接下来的步骤中还会用到!

生成的密钥将保存在rootCA.key文件中,使用以下命令用它来生成根SSL证书

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 7300 -out rootCA.pem


![root-ca-pem](/static/images/root-ca-pem.png)

填写所需信息(**密码短语**必须与第一步生成`rootCA.key`时使用的密码相匹配!)

此证书将保存在`rootCA.pem`文件中。

### <Twemoji emoji="keycap-2" /> 信任根SSL证书

要使用**根SSL证书**生成的证书,我们需要告诉操作系统信任这个**根证书**。

打开**钥匙串访问**应用程序(MacOS),选择**证书**标签:

![keychain-access](/static/images/keychain-access.png)

通过拖拽或导航到**文件 / 导入项目...**来导入`rootCA.pem`。

然后在导入的证书上**右键点击 / 显示简介**(或**双击**)

![cert-trust-setting](/static/images/cert-trust-setting.png)

展开**信任**标签,在第一个设置中选择**始终信任**,然后保存。

**钥匙串访问**随后会显示类似**"此证书被标记为此帐户信任"**的消息,这意味着你已成功信任了**根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文件:

server.js
let Koa = require('koa');
let app = new Koa();
 
app.use(async ctx => {
  ctx.body = 'Hello World';
});
 
module.exports = app

在你的应用中创建一个名为 certs/ 的目录,然后将 server.keyserver.crt 移动到该目录中。

使用 https 模块加载证书文件并创建 HTTPS 服务器:

index.js
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)
}

项目结构应该如下所示:

https-koa-project

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

http-koa

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

https-koa

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

localhost-443

在浏览器中打开 https://localhost:443,你就能看到你的应用通过 HTTPS 运行了

源代码可以在这个仓库中找到。

总结

如果你不是 Node.js 开发者,你可以搜索如何在你喜欢的技术栈中使用证书文件创建 HTTPS 服务器

希望这个指南能帮助你在本地使用 HTTPS 开发应用!

分享快乐

参考资料