本地开发如何使用HTTPS

本地开发如何使用HTTPS

本文关于localhost的表述,同样适用于127.0.0.1与[::1],因为两者都表示本机地址,也称“回环地址”。为简化说明,没有写出端口号。因此看到http://localhost时,应理解为http://localhost:{PORT}或http://127.0.0.1:{PORT}。

如果生产网站使用HTTPS,就会希望本地开发网站的行为也像HTTPS网站。如果生产网站尚未使用HTTPS,应优先切换到HTTPS。大多数时候,可以信赖http://localhost具有类似HTTPS网站的行为;但在某些情况下,仍需在本地通过HTTPS运行网站。下面看看如何实现。

需要快速操作说明,或已经读过本文?直接跳到速查表。

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

要让本地开发网站使用HTTPS,并通过https://localhost或自定义主机名https://mysite.example访问,需要TLS证书。但浏览器不会认为任意证书都有效:证书必须由浏览器信任的实体签名,这个实体称为受信任的证书颁发机构,CA。

需要创建证书,并使用设备和浏览器在本地信任的CA为它签名。mkcert可以通过几条命令完成这些工作,其工作方式如下:

  • 通过HTTPS在浏览器中打开本地运行的网站时,浏览器会检查本地开发服务器的证书。
  • 发现证书由mkcert生成的CA签名后,浏览器检查该CA是否已注册为受信任的证书颁发机构。
  • mkcert被列为受信任机构,因此浏览器信任证书并建立HTTPS连接。
mkcert工作原理图
mkcert的工作原理。

mkcert及类似工具具有多项优点:

  • mkcert专门创建符合浏览器有效证书标准的证书,并随要求与最佳实践更新。因此不必通过复杂配置或参数运行mkcert命令,也能生成正确证书。
  • mkcert是跨平台工具,团队中的任何人都可以使用。

我们推荐使用mkcert创建本地开发用TLS证书,也可以查看其他选项。

很多操作系统包含用于生成证书的库,例如openssl。与mkcert及类似工具不同,这些库可能无法始终生成正确证书,可能需要复杂命令,也不一定跨平台。

注意

设置

  1. 安装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

    上述命令完成两件事:为指定主机名生成证书,并让已经在第2步添加为本地CA的mkcert为证书签名。

    现在证书已经准备好,并由浏览器在本地信任的CA签名。只差最后一步:服务器还不知道这张证书。

  4. 配置服务器。

    现在需要告诉服务器使用HTTPS,因为开发服务器通常默认使用HTTP,并使用刚创建的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这个本地CA,所以不会出现浏览器警告。

使用mkcert:速查表

mkcert简要步骤

要让本地开发网站通过HTTPS运行:

  1. 设置mkcert。

    尚未安装时先安装,例如在macOS上:

    brew install mkcert
    

    Windows与Linux的安装方法请查看安装mkcert。

    然后创建本地CA:

    mkcert -install
  2. 创建受信任证书。
    mkcert {YOUR HOSTNAME e.g. localhost or mysite.example}

    这会创建有效证书,并由mkcert自动签名。

  3. 配置开发服务器使用HTTPS及第2步创建的证书。
  4. 完成!现在可以在浏览器中访问https://{YOUR HOSTNAME},不出现警告。

本地通过HTTPS运行网站:其他选项

自签名证书

也可以不使用mkcert这样的本地CA,而是自行签署证书。

这种方式有以下问题:

  • 浏览器并不信任你作为CA,因此会显示需要手动绕过的警告。在Chrome中,可以使用#allow-insecure-localhost标志自动绕过localhost上的警告。这种做法确实有些取巧。
  • 在不安全网络中工作时,这不安全。
  • 自签名证书的行为与受信任证书并不完全相同。
  • 它不一定比使用mkcert这样的本地CA更简单或更快。
  • 在浏览器以外使用该技术时,可能需要对服务器禁用证书验证。如果在生产环境中忘记重新启用,会很危险。
使用自签名证书时浏览器显示警告的原文截图
使用自签名证书时浏览器显示的警告。

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

通过HTTPS在浏览器中打开本地网站时,浏览器会检查本地开发服务器的证书。发现证书由你自己签名后,它会检查你是否注册为受信任CA。因为没有注册,浏览器无法信任该证书,因此显示连接不安全的警告。你可以自行承担风险继续访问;若继续,就会建立HTTPS连接。

浏览器不信任自签名证书的原因图
为什么浏览器不信任自签名证书。

由常规证书颁发机构签名的证书

还可能找到使用真正的CA,而不是本地CA,为证书签名的技术。

考虑这些方法时,需要注意:

  • 与mkcert这样的本地CA方案相比,需要更多设置工作。
  • 必须使用你拥有控制权的有效域名。因此,不能让真正的CA为以下名称签发证书:

反向代理

通过HTTPS访问本地网站的另一个办法,是使用反向代理,例如ngrok。

需要考虑:

  • 将反向代理生成的URL分享给别人后,任何持有该URL的人都可以访问本地开发网站。这在向客户演示项目时很方便;如果项目敏感,也可能是缺点。
  • 可能需要考虑价格。
  • 浏览器中的新安全措施可能影响这些工具的工作方式。

浏览器标志,不推荐

使用mysite.example这样的自定义主机名时,可以利用Chrome标志强制把mysite.example视为安全。应避免这样做,因为:

  • 必须百分之百确认mysite.example始终解析为本地地址,否则可能泄露生产凭据。
  • 这个技巧无法用于跨浏览器调试。

感谢所有审阅者与贡献者的贡献和反馈,尤其是Ryan Sleevi、Filippo Valsorda、Milica Mihajlija与Rowan Merewood。

原文主图背景由@anandu提供,来自Unsplash,经过编辑。

来源与许可

作者:Maud Nalpas。来源:web.dev:Use HTTPS for local development,2021年1月25日。本版为中文翻译,源码保持原文。所保存官方仓库版本将正文按CC BY 3.0、代码示例按Apache 2.0许可提供,完整条款见官方仓库LICENSE。主图另有上列图片署名。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容