何时以及如何在你的本地开发环境中使用 HTTPS
“在这篇文章中,关于本地主机的语句也适用于
127.0.0.1
和[::1]
,因为它们都描述了本地计算机地址,也称为“回送地址”。另外,为简单起见,未指定端口号。因此,当你看到http://localhost
时,将其读取为http://localhost:{PORT}
或http://127.0.0.1:{PORT}
。
如果你的生产网站使用 HTTPS,那么你会希望本地开发站点的表现也会和 HTTPS 站点一样。在大多数情况下,你可以相信 http://localhost
的行为类似于 HTTPS 站点。但是在某些情况下,你需要使用 HTTPS 在本地运行站点。
所以本文将针对 2 个问题展开:
何时需要在本地开发环境中使用 HTTPS? 如何在本地开发环境中使用 HTTPS?
何时需要在本地开发环境中使用 HTTPS
在本地开发时,默认情况下使用 http://localhost
。Service Workers
, Web 认证 API, 以及一些别的等都可以工作。然而,在以下情况下,你需要使用 HTTPS 进行本地开发:
在所有浏览器中以一致的方式设置安全 cookie。你需要在本地设置一个 Secure 或
SameSite: none
或具有__Host
前缀的 cookie。对于所有浏览器,仅在 HTTPS上 设置安全 cookie,而不在http://localhost
上设置安全 cookie。并且由于SameSite: none
和__Host
也要求 cookie 是安全的,因此在本地开发站点上设置此类 cookie 也需要 HTTPS。“
在本地设置安全cookie时,并非所有浏览器的行为都相同!例如,Chrome和Safari不在本地主机上设置安全cookie,但Firefox设置了。在Chrome中,这被视为错误。
调试混合内容问题。你需要在本地调试仅在 HTTPS 网站上发生的问题,而不是在 HTTP 网站上,甚至在
http://localhost
上都不会发生,例如混合内容问题。使用 HTTP/2 和更高版本。
使用需要 HTTPS 的第三方库或 API,比如 OAuth;
你使用的不是本地主机,而是本地开发的自定义主机名,例如
mysite.example
。通常,这意味着你已经覆盖了本地主机文件。在这种情况下,即使 Chrome,Edge,Safari 和 Firefox 是本地站点,默认情况下也不认为mysite.example
是安全的。因此,它的行为不会像 HTTPS 站点那样。
如何在本地开发环境中使用 HTTPS
你可能会遇到一些特殊情况,比如 http://localhost 网站的行为不像 HTTPS 网站,或者你可能只是想使用一个不是 http://localhost 网站的自定义网站名称。
推荐使用 mkcert
“mkcert 地址:https://github.com/FiloSottile/mkcert
要将 HTTPS 与你的本地开发站点一起使用并访问 https://localhost
或 https://mysite.example
(自定义主机名),你需要 TLS 证书。但是浏览器不会仅仅认为任何证书有效:你的证书需要由浏览器信任的实体(称为受信任的证书颁发机构(CA))签名。
而你需要做的就是创建一份证书,并使用你的设备和浏览器在本地信任的 CA 对其进行签名。mkcert 是一个可以帮助你通过一些命令来完成此任务的工具。运作方式如下:
如果你使用 HTTPS 在浏览器中打开本地运行站点,你的浏览器将检查本地开发服务器的证书; 当看到证书已经由 mkcert 生成的证书颁发机构签名时,浏览器检查它是否注册为受信任的证书颁发机构; mkcert 被列为受信任的权威,因此浏览器信任该证书并创建一个 HTTPS 连接。
mkcert (及其类似的工具)提供了几个好处:
mkcert 专门用于创建符合浏览器认为有效的证书,它保持更新以满足需求和最佳实践。这就是为什么你不必使用复杂的配置或参数运行 mkcert 命令来生成正确的证书; mkcert 是一个跨平台的工具,团队中的任何人都可以使用它。
mkcert 是我们推荐的用于为本地开发创建 TLS 证书的工具。你也可以查看其他选项。
许多操作系统可能包含用于产生证书的库,比如 openssl。与 mkcert 和类似的工具不同,这些库可能不能始终生成正确的证书,可能需要运行复杂的命令,而且不一定是跨平台的。
注意事项:
不要导出或共享文件 rootCA-key.pem
,因为当你在执行mkcert -install
的时候,它会自动创建;攻击者获得这个文件可以为你访问的任何站点创建路径上的攻击。他们可以拦截从你的机器发送到任何网站的安全请求,比如你的银行、医疗服务提供商或社交网络。如果你想知道它被放到哪里才是安全的,可以执行mkcert -CAROOT
。mkcert 仅仅只是被我们用于开发环境,切不可让最终用户去使用 mkcert 命令; 所有团队成员都应该独自安装和运行 mkcert 命令(不能够存储或者共享 CA 和 证书)。
设置
安装 mkcert(仅需一次):按照说明在你的操作系统上安装 mkcert:
brew install mkcert
将 mkcert 添加到本地根 CA 中,在终端运行如下命令:
mkcert -install
这将生成一个本地证书颁发机构(CA)。你的 mkcert 生成的本地 CA 在你的设备上仅受本地信任。
为你的站点生成一个由 mkcert 签名的证书。在终端中,导航到站点的根目录或者你希望证书位于的任何目录,然后执行:
mkcert localhost
如果你使用一个自定义的主机名,比如 mysite.example,运行:
mkcert mysite.example
上面的命令做了两件事:
为指定的主机名生成证书; 让 mkcert (在步骤2中添加为本地 CA)签署此证书。
到这步为止,你的证书已经就绪,并由浏览器本地信任的证书颁发机构签名。你差不多完成了,但是你的服务器还不知道你的证书!
配置你的服务器。现在需要告诉服务器使用 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...}
:
// - s 使用 HTTPS 运行服务器,-c 设置证书,-k 设置密钥
http-server -S -C {PATH/TO/CERTIFICATE-FILENAME}.pem -K {PATH/TO/CERTIFICATE-KEY-FILENAME}.pem
使用 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
|--...
那么你的开始脚本应该是这样的:
"scripts": {
"start": "HTTPS=true SSL_CRT_FILE=localhost.pem SSL_KEY_FILE=localhost-key.pem react-scripts start"
OK,你已经完成配置了。在你的浏览器中打开 https://localhost
或者https://mysite.example
你使用 HTTPS 在本地运行你的网站。你不会看到任何浏览器警告,因为你的浏览器将 mkcert 信任为本地证书颁发机构。
自签名证书
你还可以决定不使用像 mkcert 这样的本地证书颁发机构,而是自己签署证书。
不过,得小心这种方法的几个缺陷:
浏览器不信任你作为证书颁发机构,它们会显示你需要手动绕过的警告。在 Chrome 中,你可以使用这个标志 #allow-insecure-localhost
,自动绕过这个警告;如果你在不安全的网络中工作,这是不安全的; 自签名证书的行为方式与受信任证书不完全相同; 这并不一定比使用像 mkcert 这样的本地 CA 更容易或更快; 如果不在浏览器上下文中使用此技术,则可能需要禁用服务器的证书验证。忽略在生产中重新启用它将是危险的。
为什么浏览器不相信自签名证书
如果你在浏览器中使用 HTTPS 打开本地运行站点,你的浏览器将检查本地开发服务器的证书。当它看到证书是你自己签署的时候,它会检查你是否注册为受信任的证书颁发机构。因为你不是,所以你的浏览器不能信任证书; 它会显示一个警告,告诉你你的连接不安全。你可能会自行承担风险ーー如果你这样做,将创建一个 HTTPS 连接。
由普通证书颁发机构签署的证书
你还可以找到基于拥有一个实际的证书颁发机构(而不是本地的证书颁发机构)来签署证书的技术。
如果你正在考虑使用这些技巧,请记住以下几点:
与使用像 mkcert 这样的本地 CA 技术相比,你需要做更多的安装工作; 你需要使用你控制的有效域名。这意味着你不能够使用实际的证书颁发机构: localhost
以及其他的保留域名,比如 example 或者 test;任何你不能控制的域名; 无效的顶级域名
反向代理
使用 HTTPS 访问本地运行站点的另一个选择是使用反向代理,比如 ngrok。需要考虑的几点:
任何人都可以访问你的本地开发网站,只要你与他们分享一个由反向代理创建的 URL。这可以是非常方便的时候,你的项目演示给客户!如果你的项目很敏感,这也可能是一个缺点; 你可能需要考虑价格; 浏览器中新的安全措施可能会影响这些工具的工作方式。
感谢阅读
如果你觉得这篇文章对你有所帮助的话,来个分享、点赞、在看三连吧,让更多的人看到。 关注公众号「前端公虾米」,回复 资料 领取前端进阶资料,定期为你推送前端干货文章。 添加本人微信「y3517320520」,拉你进前端技术交流群和大厂同学一起交流学习。