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


mkcert可以生成证书并将证书加入操作系统的信任列表,因此将证书配置到你的测试环境之后,可以直接访问 https://localhost:3000 而不会有任何警告。 要测试类似生产环境的 CORS ,比如前后端完全分离的架构,https 必不可少。
那么如何在局域网内完成类似的效果呢?比如 https://192.168.3.168 。或者使用 vscode remote ssh 的时候,在本地打开本地的浏览器可以访问,但是在 remote 端,有时候需要访问一下呢?也就是说需要一个分布式的 mkcert ,cert-ctrl,这个是我们写的。self-ca 在 这里生成,在每个需要访问你的测试服务的电脑上安装客户端即可。对于某些生产环境的管理页面,如果不需要公开访问,直接用自签发的 mTLS 即可。

题外话: 有些人对文章的内容不感兴趣,对文章中提到别人的软件也没关系,唯独对提到作者自己的软件耿耿于怀,其实大可不必,最好的做法是不要去理这样的贴子如果你觉得没有价值。大家都不理它,它就自然下沉消失不见了。
1 willbeok 1 天前 能 get 到需要解决的场景问题,但这个工具的介绍有点看不太明白。mkcert 安装后浏览器会信任证书,cert-ctrl 也能自动完成信任? self-sa 是一个命令行,没看明白作用是什么,有没有这套组合的系统架构图说明一下呢 |
2 ff521 1 天前 只要不是 AI 生成的内容就好 (主要是和本站宗旨不符,回复都不能 AI,主题反而随便 AI 生成,让人感觉割裂) |
3 Rache1 1 天前 你想要在其机器也能获得 https 访问,只需要按照 mkcert 的说明,把证书发其他机器然后安装信任根证书就好了。 https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installing-the-ca-on-other-systems:~:text=Installing%20the%20CA,key.pem. |
4 jianglibo OP PRO @willbeok 如果你注册一下, 这个架构就非常清晰了,cert-ctrl 登陆之后,类似于 cloudflare,tailscale 客户端,它和[中心服务器]( https://api.cjj365.cc/r/v2ex1)交互,你在 web 端的 CA ,证书全部会自动分发,这样描述你能明白吗? |
5 chaoshui 1 天前 我认为解决这个问题的方式是使用代理,而不是在你的操作系统里安装莫名奇妙的证书。 Vite/Webpack/Nextjs 不都有代理解决方案吗? |
6 jianglibo OP PRO @Rache1 一般来说证书固定在提供服务的机器上,http server,mail server etc. 而 ca 需要导入到需要访问这个服务的机器上,mkcert 的使用场景本机,如果你要达成从其它机器访问又变成手动模式了,如果是手动模式,那么你直接用 openssl 好了。工具的目的是让你不要去折腾,或者一次性设置,在整个职业生涯中可重复利用以节约时间和脑力。 |
8 jianglibo OP PRO @chaoshui 代理就是避开了 CORS ,你可能需要更深层的思考和实践。访问[这里]( https://api.cjj365.cc/r/v2ex1),然后启用 chrome 的 dev panel ,仔细观察请求,你会更深的理解这个问题。 |
9 jianglibo OP PRO @xitler 为了便于你理解,比如有一个 api 服务器, https://api.some.where.support.cors , 你从服务器一侧调用没有任何问题,但是你直接从你的浏览器调用这个 api 为发生什么, 想象一下,实践一下,不会在感到迷惑,提高了自己的水平. |
10 jianglibo OP PRO |
11 Rache1 1 天前 @jianglibo 你这不也是要在访问侧安装东西吗,mkcert 只是需要你把那个 CA 导入到访问侧的主机上就好了(基于这个 CA 生成的证书都不需要在管了),还不需要额外装软件呢。 |
12 jianglibo OP PRO @Rache1 就是涉及到 ca 的复制、导入,系统重装之后就全部要重来了,原来的证书和 ca 都不见了,cert-ctrl 不需要在机器之间复制,重装系统也没有关系。当然也不是没有代价,就是你提到的需要安装客户端。 |
13 zcf0508 1 天前 加证书不解决跨域问题吧 |
14 liaozzzzzz 1 天前 via Android nginx:? |
16 jianglibo OP PRO @zcf0508 从机制上来说证书和 cors 关系不大,但在实际使用中密切相关。 你可以试试看,http://localhost:3000 然后 cors 请求一个 https 或者 http 的第三方站点,你就会体会到为什么相关,chrome 可能甚至不允许你用 http 跨域。 |
17 jianglibo OP PRO @shintendo 你不明白,而且也不想进步,那也没办法,我是希望能帮助到有求知心的人。避开 CORS 就代表 CORS 不需要了吗?你作为前端甚至不知道 CORS 的使用场景,还叽里咕噜。 |
18 v2er119 1 天前 如果在代理上用,请求和响应的内容都是可以解密? |
19 jianglibo OP PRO @v2er119 代理这个词不准确,刚才评论提到的代理都是在公司内部开发时为了避开 CORS 而为之,属于代取,但是不能暴露进入生产环境之后可能遇到的 CORS 问题。 |
20 pingdog 1 天前 via iPhone 引用 @shintendo 的话“叽里咕噜说一堆” 从头到尾看了两遍,才发现 OP 只是在推广自己的项目 > 也就是说需要一个分布式的 mkcert ,cert-ctrl ,这个是我们写的。 dev env 直接让 SRE 在 cors policy 加多一个 localhost 不就行了吗,搞这么复杂,反正 dev 上的资源随便 |
22 xdzhang 1 天前 前段时间遇到 2 回这个情况,当时还是挺烦的. |
23 jianglibo OP PRO @pingdog 那 Cookies + CORS 如何解决?必须用 https 了吧。:),所以在 chrome 下你无法调试登陆,在你提到的场景下,更加需要 cert-ctrl ,下次你公司碰到这个问题时,希望你能想到这个贴子。 Cross-site cookies REQUIRE SameSite=None; Secure But Secure cookies cannot be set over HTTP |
25 sofukwird 1 天前 申请个域名指向本地, 然后使用证书管理工具获取对应的证书 |
28 sofukwird 1 天前 CORS 不是坑是特性 |
29 zcf0508 1 天前 @sofukwird #25 我的工具 https://github.com/zcf0508/unplugin-https-reverse-proxy 可以自动在本地添加 host 并且配置证书,无缝调试 |
30 xitler 1 天前 我觉得不太行,而且也根本不需要什么 https 的 localhost 。开发,测试,rc ,线上环境不做配置隔离吗,一套对一套 |
31 ragnaroks 1 天前 难道只有我是 https://localhost.mydomain.com:3443/ ? |
32 sofukwird 1 天前 真自签证书的话我更喜欢用 XCA 自签证书管理 |
34 ltaoo1o 1 天前 重点「前端开发过程的 CORS 问题」,正如前面提到,无论 vite 还是 webpack 都有解决方案并且很方便就能使用,完全没必要额外安装什么东西,尤其是根证书这种存在风险的东西。 题外话:这就是软文,软文都是被排斥的,因为不够客观,经常是为了推自己的东西,强行构造出一个场景或者问题,从而引入自己的东西,都不考虑实际情况,就比如这篇帖子 要推广就大大方方的推,好东西从不被排斥 |
35 liuhuihao 1 天前 ?开发环境的话难道不应该是 vite 或 webpack 的 devServer 转发一下的事儿吗,如果是线上直接配一下后台的 CORS 返回头或者 nginx 代理一下不都能解决问题吗 为啥要搞个证书嘞 |
36 jianglibo OP PRO @liuhuihao 我完全理解你的困惑,大部分人可能没有真正接触过前后端完全分离的架构,前端是静态的 html ,所有逻辑在 api 一侧,包括登陆信息等。 当 cors 遇上 cookie 时,现代浏览器会有严格的限制,甚至必须是 https 。https://cjj365.cc 是 html 的静态文件,是用静态文件生成器生成的。 |
37 Ketteiron 1 天前 你应该更直接地表述这个工具到底解决了什么场景下的问题。 什么时候有用?即使用 cookie 鉴权且后端设置了 SameSite=None; Secure 且需要远程访问本地运行的项目且需要保证开发环境与实际环境完全一致。 这样就能劝退完全用不上的 99.99% 用户了。 |
38 KellyAlsa 1 天前 本地开发应该不需要搭建 https 的服务吧 |
39 jianglibo OP PRO @Ketteiron 你比大多数评论者知道其中的微妙,不是远程访问的问题,在本地调试也是一样,在需要鉴权 cookie 的情况下,本地调试也需要 https.关于工具的用处,自认证证书的签发是很小一部分功能,主要是 public 证书签发。 |
40 adgfr32 1 天前 via Android 生产环境是否有 cors 问题,应该通过上线前端到端测试+灰度来避免,而不是你这种奇技淫巧。 你的做法和本地 nginx 代理没啥优势,只要上线前没有实际环境校验过,谁能保证自己方案一定过呢? |
42 a132811 1 天前 @zcf0508 我以前的做法,本地开发时直接用一键命令行的正向代理:证书、域名都本地生成、不侵入服务端 https://github.com/ahuigo/selfhttps |
43 explore365 1 天前 用 openssl 或 mkcert 生成一个长期几十年的自签 CA 证书+localhost&127.0.0.1 域名证书,以后在每个测试的客户端安装这个 CA 自签证书即可。 |
44 Ketteiron 1 天前 我来简单总结下吧。 举个例子,本地使用 https:localhost ,浏览器需要一个受信任的证书,这里需要 mkcert 签发一个临时信任证书。 如果从其他地方例如手机访问局域网,手机的浏览器会警告,因为它没有信任证书。 那么"分布式" mkcert 如何提供证书,其实是服务端下发私有根证书。 简单来说,通过自建一个私有 CA ,安装软件等于信任这个 CA ,因此不会警告。 当然这带来了安全风险,自建方案也存在隐患。 一般情况下 vite + vite-plugin-mkcert 就行了 OP 的工具其实是解决了自动化复制 rootCA.pem 的操作。你说有用吧,确实有用,但我猜愿意用的没几个。 |
45 chenluo0429 1 天前 via Android 遇到了一条河过不去怎么办? 普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过 动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去 OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。 |
46 chenluo0429 1 天前 via Android 遇到了一条河过不去怎么办? 普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过 动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去 OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。 |
47 jianglibo OP PRO @Ketteiron 评论里面算比较了解 CORS 的了,不过 cert-ctrl 不仅仅分发 CA ,也完成信任操作,比如 windows,linux,freebsd,macos,firefox 等等,也分发证书(电脑重装什么的不丢)。简单说,就是本来是命令行操作,机器之间复制的行为,变成 web 端的资源,然后通过 cert-ctrl 完成这种操作,比如证书更新之后执行脚本什么的。因为我自己的系统就有大量的证书,mysql ,redis ,rabbitmq ,mail server ,http 静态服务器,api 服务器等等,需要一个统一的管理和分发机制。 |
span class="no">48 AV1 1 天前 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 |
50 patrickyoung 22 小时 6 分钟前 |
51 datou 21 小时 23 分钟前 开发环境配上测试域名 给测试域名签好 tls 证书 完活儿 |
52 sagnitude 21 小时 14 分钟前 自己弄个便宜点的域名,弄个服务器做自动续签,弄个 crontab 定期下载到本地,开发电脑上改 hosts ,本地搭建 nginx ,浏览器直接打开 hosts 的域名,好得很,没必要死磕 localhost |
53 jiangzm 21 小时 7 分钟前 全部看完了也没清楚浏览器、web 服务、cert-ctrl 、中心服务器 这四者是怎么交互的。没有条理的说一大堆还不如贴一张架构/交互图就一眼明了。 按上面讲的 cert-ctrl 像 cloudflare ,那就是通过中间代理完成证书分发和代理请求,那问题来了用户在浏览器访问的域名是什么?还是 localhost 吗,中心服务器是用户需要部署的服务还是用你的? 但是又好像说是通过安装代理客户端 cert-ctrl 同步自动分发的证书安装到本地?(另外多个代理不是叫分布式) |
54 unco020511 10 小时 28 分钟前 有一个东西叫代理,你在本地开发的时候,起个 whistle,哪有那么复杂啊 prod.xxx.com localhost:3000 api-prod.xxx.com locahost:5000 你浏览器直接访问 prod.xxx.com 你想怎么玩怎么玩,不论的你前端和服务端在哪台机器哪个环境,无所谓,代理都会帮你处理好,不存在任何跨域和证书的问题,你本地是完全和生产环境等价的 |
55 unco020511 10 小时 21 分钟前 OP 是动脑筋思考了的,但解决方案有些绕远了 |
56 longzhiwuing 6 小时 13 分钟前 op 做的是一个『伪 CA 』,让浏览器误认为本来不被『真正 CA 』认证的域名变成『合法』的,进而『骗』过浏览器访问非公网的域名对应的服务。为什么要这么做?因为他的前端和后端接口通信得『同域』?,否则浏览器提示 CORS 错误? 是这么理解么? |
57 jianglibo OP PRO @unco020511 如果你愿意请简单测试一下,http://localhost 返回一个 html 文件 A ,有一个 form ,username/password , 通过 ajax 发送到 http://localhost:3000 ,登陆 http://localhost:3000 ,然后在 A 页面显示登陆状态。 先不要急着分析,先试试看。等你回复。 |
58 jianglibo OP PRO @longzhiwuing 不存在真 CA 和假 CA ,只有信任的和不信任的 CA ,系统默认信任的 CA 和我愿意信任的 CA 。 |