使用 HTTPS 进行本地开发

大多数情况下,http://localhost 的行为与 HTTPS 类似,可用于开发目的。不过,在某些特殊情况下,例如使用自定义主机名或跨浏览器使用安全 Cookie,您需要明确设置开发网站,使其行为类似于 HTTPS,以便准确表示网站在生产环境中的运作方式。(如果您的生产网站不使用 HTTPS,请优先切换到 HTTPS)。

本页介绍了如何在本地使用 HTTPS 运行网站。

如需查看简要说明,请参阅 mkcert 快速参考。**

使用 mkcert 在本地通过 HTTPS 运行网站(推荐)

若要为本地开发网站使用 HTTPS 并访问 https://localhost 或 https://mysite.example(自定义主机名),您需要一个由设备和浏览器信任的实体(称为受信任的证书授权机构 [CA])签名的 TLS 证书。 在创建 HTTPS 连接之前,浏览器会检查开发服务器的证书是否由受信任的 CA 签名。

我们建议使用跨平台 CA mkcert 来创建和签署证书。如需了解其他实用选项,请参阅使用 HTTPS 在本地运行网站:其他选项。

许多操作系统都包含用于创建证书的库,例如 openssl。不过,它们比 mkcert 更复杂、更不可靠,而且不一定支持跨平台,因此不太适合大型开发者团队。

设置

  1. 安装 mkcert(仅一次)。

    按照说明在您的操作系统上安装 mkcert。例如,在 macOS 上:

    brew install mkcert
    brew install nss # if you use Firefox
    
  2. 将 mkcert 添加到本地根 CA。

    在终端中,运行以下命令:

    mkcert -install
    

    这会生成一个本地证书授权机构 (CA)。 mkcert 生成的本地 CA 仅在您的设备上本地受信任。

  3. 为您的网站生成由 mkcert 签名的证书。

    在终端中,前往网站的根目录或您希望保存证书的任何目录。

    然后运行以下命令:

    mkcert localhost
    

    如果您使用的是自定义主机名(例如 mysite.example),请运行:

    mkcert mysite.example
    

    此命令会执行两项操作:

    • 为您指定的主机名生成证书。
    • 让 mkcert 为证书签名。

    您的证书现已准备就绪,并由浏览器在本地信任的证书授权机构签名。

  4. 将服务器配置为使用 HTTPS 和您刚刚创建的 TLS 证书。

    具体实现方法取决于您的服务器。以下是一些示例:

    👩🏻‍💻 使用 Node:

    server.js(替换 {PATH/TO/CERTIFICATE...} 和 {PORT}):

    const https = require('https');
    const fs = require('fs');
    const options = {
      key: fs.readFileSync('{PATH/TO/CERTIFICATE-KEY-FILENAME}.pem'),
      cert: fs.readFileSync('{PATH/TO/CERTIFICATE-FILENAME}.pem'),
    };
    https
      .createServer(options, function (req, res) {
        // server code
      })
      .listen({PORT});
    

    👩🏻‍💻 使用 http-server:

    按如下方式启动服务器(替换 {PATH/TO/CERTIFICATE...}):

    http-server -S -C {PATH/TO/CERTIFICATE-FILENAME}.pem -K {PATH/TO/CERTIFICATE-KEY-FILENAME}.pem
    

    -S 使用 HTTPS 运行服务器,而 -C 设置证书,-K 设置密钥。

    👩🏻‍💻 使用 React 开发服务器:

    按如下所示修改 package.json,并替换 {PATH/TO/CERTIFICATE...}:

    "scripts": {
    "start": "HTTPS=true SSL_CRT_FILE={PATH/TO/CERTIFICATE-FILENAME}.pem SSL_KEY_FILE={PATH/TO/CERTIFICATE-KEY-FILENAME}.pem react-scripts start"
    

    例如,如果您在网站的根目录中为 localhost 创建了证书:

    |-- my-react-app
        |-- package.json
        |-- localhost.pem
        |-- localhost-key.pem
        |--...
    

    那么您的 start 脚本应如下所示:

    "scripts": {
        "start": "HTTPS=true SSL_CRT_FILE=localhost.pem SSL_KEY_FILE=localhost-key.pem react-scripts start"
    

    👩🏻‍💻 其他示例:

  5. 在浏览器中打开 https://localhost 或 https://mysite.example,仔细检查您是否正在使用 HTTPS 在本地运行网站。您不会看到任何浏览器警告,因为您的浏览器信任 mkcert 作为本地证书授权机构。

mkcert 快速参考

mkcert 快速参考

如需使用 HTTPS 运行本地开发网站,请执行以下操作:

  1. 设置 mkcert。

    如果您尚未安装 mkcert,请先安装,例如在 macOS 上:

    brew install mkcert

    如需查看 Windows 和 Linux 说明,请参阅安装 mkcert。

    然后,创建本地证书授权机构:

    mkcert -install
  2. 创建可信证书。

    mkcert {YOUR HOSTNAME e.g. localhost or mysite.example}

    这会创建一个由 mkcert 自动签名的有效证书。

  3. 将开发服务器配置为使用 HTTPS 和您在第 2 步中创建的证书。

您现在可以在浏览器中访问 https://{YOUR HOSTNAME},而不会收到警告

</div>

使用 HTTPS 在本地运行网站:其他选项

以下是设置证书的其他方法。这些方法通常比使用 mkcert 更复杂或风险更高。

自签名证书

您也可以决定不使用 mkcert 等本地证书授权机构,而是自行签署证书。这种方法存在一些缺陷:

  • 浏览器不信任您作为证书授权机构,因此会显示您需要手动绕过的警告。在 Chrome 中,您可以使用标志 #allow-insecure-localhost 在 localhost 上自动绕过此警告。
  • 如果您在不安全的网络中工作,这样做是不安全的。
  • 它不一定比使用 mkcert 等本地 CA 更简单或更快捷。
  • 自签名证书的行为与可信证书的行为不完全相同。
  • 如果您未在浏览器上下文中使用此方法,则需要为服务器停用证书验证。如果忘记在生产环境中重新启用该功能,则会导致安全问题。
使用自签名证书时浏览器显示的警告的屏幕截图。
使用自签名证书时浏览器显示的警告。

如果您未指定证书,React 和 Vue 的开发服务器 HTTPS 选项会在后台创建自签名证书。这种方法很快,但会遇到与自签名证书相同的浏览器警告和其他问题。幸运的是,您可以使用前端框架的内置 HTTPS 选项,并指定使用 mkcert 或类似工具创建的本地可信证书。如需了解详情,请参阅将 mkcert 与 React 搭配使用示例。

为什么浏览器不信任自签名证书?

如果您在浏览器中使用 HTTPS 打开本地运行的网站,浏览器会检查本地开发服务器的证书。当系统发现您自己签署了证书时,会检查您是否已注册为受信任的证书授权机构。由于您不是,因此您的浏览器无法信任该证书,并会显示一条警告,告知您连接不安全。如果您继续操作,系统仍会创建 HTTPS 连接,但您需要自行承担风险。

图表:为什么浏览器不信任自签名证书。
为什么浏览器不信任自签名证书。

由常规证书授权机构签名的证书

您也可以使用由官方 CA 签名的证书。这会带来以下复杂情况:

  • 与使用 mkcert 等本地 CA 技术相比,您需要执行更多设置工作。
  • 您需要使用您控制的有效域名。这意味着您无法将官方 CA 用于以下用途:
    • localhost 和其他预留域名,例如 example 或 test。
    • 您无法控制的任何域名。
    • 顶级域名无效。如需了解详情,请参阅有效顶级域名列表。

反向代理

另一种通过 HTTPS 访问本地运行的网站的方法是使用反向代理,例如 ngrok。这样做会带来以下风险:

  • 您与之分享反向代理网址的任何人都可以访问您的本地开发网站。这有助于向客户演示项目,但也可能导致未经授权的人员分享敏感信息。
  • 某些反向代理服务会收取使用费,因此价格可能是您选择服务时需要考虑的一个因素。
  • 浏览器中的新安全措施可能会影响这些工具的运作方式。

如果您在 Chrome 中使用自定义主机名(例如 mysite.example),则可以使用标志强制浏览器将 mysite.example 视为安全。避免这样做的原因如下:

  • 您需要 100% 确定 mysite.example 始终解析为本地地址。否则,您可能会泄露生产凭据。
  • 此标志仅适用于 Chrome,因此您无法跨浏览器进行调试。

非常感谢所有审核者和贡献者(尤其是 Ryan Sleevi、Filippo Valsorda、Milica Mihajlija 和 Rowan Merewood)的贡献和反馈。