关于 https://localhost, https://127.0.0.1, CORS 那些事

1 月 28 日
 jianglibo

前端在开发的过程中有没有碰到过 CORS 的坑呢?欢迎提问,我也乐于分享(不是我更懂,只是碰到过而已)。

mkcert可以生成证书并将证书加入操作系统的信任列表,因此将证书配置到你的测试环境之后,可以直接访问 https://localhost:3000 而不会有任何警告。 要测试类似生产环境的 CORS ,比如前后端完全分离的架构,https 必不可少。

那么如何在局域网内完成类似的效果呢?比如 https://192.168.3.168 。或者使用 vscode remote ssh 的时候,在本地打开本地的浏览器可以访问,但是在 remote 端,有时候需要访问一下呢?也就是说需要一个分布式的 mkcert ,cert-ctrl,这个是我们写的。self-ca 在 这里生成,在每个需要访问你的测试服务的电脑上安装客户端即可。对于某些生产环境的管理页面,如果不需要公开访问,直接用自签发的 mTLS 即可。

题外话: 有些人对文章的内容不感兴趣,对文章中提到别人的软件也没关系,唯独对提到作者自己的软件耿耿于怀,其实大可不必,最好的做法是不要去理这样的贴子如果你觉得没有价值。大家都不理它,它就自然下沉消失不见了。

6928 次点击
所在节点    程序员
62 条回复
jianglibo
1 月 28 日
你根本不知道我们在说什么,问一下 @Ketteiron ,他知道。
a132811
1 月 28 日
@zcf0508 我以前的做法,本地开发时直接用一键命令行的正向代理:证书、域名都本地生成、不侵入服务端  https://github.com/ahuigo/selfhttps
explore365
1 月 28 日
用 openssl 或 mkcert 生成一个长期几十年的自签 CA 证书+localhost&127.0.0.1 域名证书,以后在每个测试的客户端安装这个 CA 自签证书即可。
Ketteiron
1 月 28 日
我来简单总结下吧。
举个例子,本地使用 https:localhost ,浏览器需要一个受信任的证书,这里需要 mkcert 签发一个临时信任证书。
如果从其他地方例如手机访问局域网,手机的浏览器会警告,因为它没有信任证书。
那么"分布式" mkcert 如何提供证书,其实是服务端下发私有根证书。

简单来说,通过自建一个私有 CA ,安装软件等于信任这个 CA ,因此不会警告。
当然这带来了安全风险,自建方案也存在隐患。

一般情况下 vite + vite-plugin-mkcert 就行了
OP 的工具其实是解决了自动化复制 rootCA.pem 的操作。你说有用吧,确实有用,但我猜愿意用的没几个。
chenluo0429
1 月 28 日
遇到了一条河过不去怎么办?
普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过
动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去
OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。
chenluo0429
1 月 28 日
遇到了一条河过不去怎么办?
普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过
动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去
OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。
jianglibo
1 月 28 日
@Ketteiron 评论里面算比较了解 CORS 的了,不过 cert-ctrl 不仅仅分发 CA ,也完成信任操作,比如 windows,linux,freebsd,macos,firefox 等等,也分发证书(电脑重装什么的不丢)。简单说,就是本来是命令行操作,机器之间复制的行为,变成 web 端的资源,然后通过 cert-ctrl 完成这种操作,比如证书更新之后执行脚本什么的。因为我自己的系统就有大量的证书,mysql ,redis ,rabbitmq ,mail server ,http 静态服务器,api 服务器等等,需要一个统一的管理和分发机制。
AV1
1 月 28 日
localhost 和 127.0.0.1 即使在 http 下默认也是安全上下文,没必要 https 。
你在 http://localhost 下执行 JS `console.log(isSecureContext)` 看它打印的是不是 true 。
参见 https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Secure_Contexts#potentially_trustworthy_origins
jianglibo
1 月 28 日
@AV1 实践. test and verify.
patrickyoung
1 月 28 日
楼主完全不懂自己写的东西。

AI 生成 /go/promotion

@livid
datou
1 月 29 日
开发环境配上测试域名

给测试域名签好 tls 证书

完活儿
sagnitude
1 月 29 日
自己弄个便宜点的域名,弄个服务器做自动续签,弄个 crontab 定期下载到本地,开发电脑上改 hosts ,本地搭建 nginx ,浏览器直接打开 hosts 的域名,好得很,没必要死磕 localhost
jiangzm
1 月 29 日
全部看完了也没清楚浏览器、web 服务、cert-ctrl 、中心服务器 这四者是怎么交互的。没有条理的说一大堆还不如贴一张架构/交互图就一眼明了。

按上面讲的 cert-ctrl 像 cloudflare ,那就是通过中间代理完成证书分发和代理请求,那问题来了用户在浏览器访问的域名是什么?还是 localhost 吗,中心服务器是用户需要部署的服务还是用你的?

但是又好像说是通过安装代理客户端 cert-ctrl 同步自动分发的证书安装到本地?(另外多个代理不是叫分布式)
unco020511
1 月 29 日
有一个东西叫代理,你在本地开发的时候,起个 whistle,哪有那么复杂啊
prod.xxx.com localhost:3000
api-prod.xxx.com locahost:5000

你浏览器直接访问 prod.xxx.com
你想怎么玩怎么玩,不论的你前端和服务端在哪台机器哪个环境,无所谓,代理都会帮你处理好,不存在任何跨域和证书的问题,你本地是完全和生产环境等价的
unco020511
1 月 29 日
OP 是动脑筋思考了的,但解决方案有些绕远了
longzhiwuing
1 月 29 日
op 做的是一个『伪 CA 』,让浏览器误认为本来不被『真正 CA 』认证的域名变成『合法』的,进而『骗』过浏览器访问非公网的域名对应的服务。为什么要这么做?因为他的前端和后端接口通信得『同域』?,否则浏览器提示 CORS 错误?
是这么理解么?
jianglibo
1 月 29 日
@unco020511 如果你愿意请简单测试一下,http://localhost 返回一个 html 文件 A ,有一个 form ,username/password , 通过 ajax 发送到 http://localhost:3000 ,登陆 http://localhost:3000 ,然后在 A 页面显示登陆状态。
先不要急着分析,先试试看。等你回复。
jianglibo
1 月 29 日
@longzhiwuing 不存在真 CA 和假 CA ,只有信任的和不信任的 CA ,系统默认信任的 CA 和我愿意信任的 CA 。
aalivexy
1 月 30 日
我遇到这种问题的时候就是手动在需要 remote 端打开一下前端和后端的页面,后端找个 health check 的端点,俩页面直接访问都肯定不信任 TLS ,两个都点击忽略,然后访问前端,前端里调用后端就正常了。这时候即便不信任 TLS 证书浏览器针对这俩都会放行,所以可以访问。

这么做的好处是不需要信任根证书,临时用一下很方便,没有任何安全问题,缺点也是只能临时用一下(不过都开发环境了也够用)

如果真要想一劳永逸解决这个问题,其实也可以用 acme 申请默认受信任的证书,服务端用 letsencrypt 之类的证书就好了,开发环境也是可以用 acme 的啊,客户端默认信任的,dns 解析到内网 192.168.3.168 你的开发机,开发机配个 acme 就好了,没那么复杂。

大家可能不太会倾向于用这种东西的原因主要还是信任,信任这个东西不是说东西好用就够的,楼主的这个东西本质上就是自建一个 CA ,这种安全基础设施没有有公信力的第三方审计估计很少有人敢用。
unco020511
1 月 30 日
@jianglibo #57 我懂你意思啊,还是那句话,用代理就可以很方便的解决,我在浏览器不会去访问 localhost,我访问的是域名,包括服务也是一样,访问的是真实域名,只不过通过代理打到你本地的项目上,这样都在一个域下,而且有真实的证书,你的生产环境是怎么访问的,在本地就是怎么访问

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1188890

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX