• 请不要在回答技术问题时复制粘贴 AI 生成的内容
jianglibo
V2EX  ›  程序员

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

  •  
  •   jianglibo ·
    PRO
    · Jan 28 · 7207 views
    This topic created in 282 days ago, the information mentioned may be changed or developed.

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

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

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

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

    62 replies  •  2026-02-01 00:02:07 +08:00
    willbeok
    willbeok
    Jan 28
    1
    能 get 到需要解决的场景问题,但这个工具的介绍有点看不太明白。mkcert 安装后浏览器会信任证书,cert-ctrl 也能自动完成信任? self-sa 是一个命令行,没看明白作用是什么,有没有这套组合的系统架构图说明一下呢
    ff521
    ff521
    Jan 28
    2
    只要不是 AI 生成的内容就好 (主要是和本站宗旨不符,回复都不能 AI,主题反而随便 AI 生成,让人感觉割裂)
    Rache1
    Rache1
    Jan 28
    3
    你想要在其机器也能获得 https 访问,只需要按照 mkcert 的说明,把证书发其他机器然后安装信任根证书就好了。


    https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installing-the-ca-on-other-systems:~:text=Installing%20the%20CA,key.pem.
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    4
    @willbeok 如果你注册一下, 这个架构就非常清晰了,cert-ctrl 登陆之后,类似于 cloudflare,tailscale 客户端,它和[中心服务器]( https://api.cjj365.cc/r/v2ex1)交互,你在 web 端的 CA ,证书全部会自动分发,这样描述你能明白吗?
    chaoshui
    chaoshui
    Jan 28
    5
    我认为解决这个问题的方式是使用代理,而不是在你的操作系统里安装莫名奇妙的证书。
    Vite/Webpack/Next.js 不都有代理解决方案吗?
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    6
    @Rache1 一般来说证书固定在提供服务的机器上,http server,mail server etc. 而 ca 需要导入到需要访问这个服务的机器上,mkcert 的使用场景本机,如果你要达成从其它机器访问又变成手动模式了,如果是手动模式,那么你直接用 openssl 好了。工具的目的是让你不要去折腾,或者一次性设置,在整个职业生涯中可重复利用以节约时间和脑力。
    xitler
    xitler
    Jan 28
    7
    @chaoshui +1 看的我有点莫名其妙了
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    8
    @chaoshui 代理就是避开了 CORS ,你可能需要更深层的思考和实践。访问[这里]( https://api.cjj365.cc/r/v2ex1),然后启用 chrome 的 dev panel ,仔细观察请求,你会更深的理解这个问题。
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    9
    @xitler 为了便于你理解,比如有一个 api 服务器, https://api.some.where.support.cors , 你从服务器一侧调用没有任何问题,但是你直接从你的浏览器调用这个 api 为发生什么, 想象一下,实践一下,不会在感到迷惑,提高了自己的水平.
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    10
    @xitler 或者你直接从浏览器调用我的 api 服务器作为测试好了 https://api.cjj365.cc , 我的设置不允许除了 https://cjj365.cc 之外的网页调用。
    Rache1
    Rache1
    Jan 28
    11
    @jianglibo 你这不也是要在访问侧安装东西吗,mkcert 只是需要你把那个 CA 导入到访问侧的主机上就好了(基于这个 CA 生成的证书都不需要在管了),还不需要额外装软件呢。
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    12
    @Rache1 就是涉及到 ca 的复制、导入,系统重装之后就全部要重来了,原来的证书和 ca 都不见了,cert-ctrl 不需要在机器之间复制,重装系统也没有关系。当然也不是没有代价,就是你提到的需要安装客户端。
    zcf0508
    zcf0508
    Jan 28
    13
    加证书不解决跨域问题吧
    liaozzzzzz
    liaozzzzzz
    Jan 28 via Android
    14
    nginx:?
    shintendo
    shintendo
    Jan 28
    15
    @jianglibo "代理只是避开了 CORS" 这不就是目的吗?叽里咕噜说一堆什么呢
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    16
    @zcf0508 从机制上来说证书和 cors 关系不大,但在实际使用中密切相关。 你可以试试看,http://localhost:3000 然后 cors 请求一个 https 或者 http 的第三方站点,你就会体会到为什么相关,chrome 可能甚至不允许你用 http 跨域。
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    17
    @shintendo 你不明白,而且也不想进步,那也没办法,我是希望能帮助到有求知心的人。避开 CORS 就代表 CORS 不需要了吗?你作为前端甚至不知道 CORS 的使用场景,还叽里咕噜。
    v2er119
    v2er119
    Jan 28
    18
    如果在代理上用,请求和响应的内容都是可以解密?
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    19
    @v2er119 代理这个词不准确,刚才评论提到的代理都是在公司内部开发时为了避开 CORS 而为之,属于代取,但是不能暴露进入生产环境之后可能遇到的 CORS 问题。
    pingdog
    pingdog
    Jan 28 via iPhone
    20
    引用 @shintendo 的话“叽里咕噜说一堆”

    从头到尾看了两遍,才发现 OP 只是在推广自己的项目
    > 也就是说需要一个分布式的 mkcert ,cert-ctrl ,这个是我们写的。

    dev env 直接让 SRE 在 cors policy 加多一个 localhost 不就行了吗,搞这么复杂,反正 dev 上的资源随便
    xitler
    xitler
    Jan 28
    21
    @jianglibo ?那我问你,如果你这个证书,泄露了怎么办,谁都可以远程调用你的生产环境
    xdzhang
    xdzhang
    Jan 28
    22
    前段时间遇到 2 回这个情况,当时还是挺烦的.
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    23
    @pingdog 那 Cookies + CORS 如何解决?必须用 https 了吧。:),所以在 chrome 下你无法调试登陆,在你提到的场景下,更加需要 cert-ctrl ,下次你公司碰到这个问题时,希望你能想到这个贴子。

    Cross-site cookies REQUIRE SameSite=None; Secure
    But Secure cookies cannot be set over HTTP
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    24
    @xitler 选择 device wrapper only ,服务器端无法解密,必须时客户端的私钥解密,私钥从不离开你的服务器。
    sofukwird
    sofukwird
    Jan 28
    25
    申请个域名指向本地, 然后使用证书管理工具获取对应的证书
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    26
    @xitler 选择有效期 6 天的证书,以保证最大的安全性。
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    27
    @sofukwird 你的解决方案可行,但经常更新比较烦,自认证证书设个 20 年,整个职业生涯哦都不需要更新了。
    sofukwird
    sofukwird
    Jan 28
    28
    CORS 不是坑是特性
    zcf0508
    zcf0508
    Jan 28
    29
    @sofukwird #25 我的工具 https://github.com/zcf0508/unplugin-https-reverse-proxy 可以自动在本地添加 host 并且配置证书,无缝调试
    xitler
    xitler
    Jan 28
    30
    我觉得不太行,而且也根本不需要什么 https 的 localhost 。开发,测试,rc ,线上环境不做配置隔离吗,一套对一套
    ragnaroks
    ragnaroks
    Jan 28
    31
    sofukwird
    sofukwird
    Jan 28
    32
    真自签证书的话我更喜欢用 XCA 自签证书管理
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    33
    @sofukwird XCA 是桌面程序,我的是网页版有什么区别呢?
    ltaoo1o
    ltaoo1o
    Jan 28
    34
    重点「前端开发过程的 CORS 问题」,正如前面提到,无论 vite 还是 webpack 都有解决方案并且很方便就能使用,完全没必要额外安装什么东西,尤其是根证书这种存在风险的东西。

    题外话:这就是软文,软文都是被排斥的,因为不够客观,经常是为了推自己的东西,强行构造出一个场景或者问题,从而引入自己的东西,都不考虑实际情况,就比如这篇帖子

    要推广就大大方方的推,好东西从不被排斥
    liuhuihao
    liuhuihao
    Jan 28
    35
    ?开发环境的话难道不应该是 vite 或 webpack 的 devServer 转发一下的事儿吗,如果是线上直接配一下后台的 CORS 返回头或者 nginx 代理一下不都能解决问题吗

    为啥要搞个证书嘞
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    36
    @liuhuihao 我完全理解你的困惑,大部分人可能没有真正接触过前后端完全分离的架构,前端是静态的 html ,所有逻辑在 api 一侧,包括登陆信息等。 当 cors 遇上 cookie 时,现代浏览器会有严格的限制,甚至必须是 https 。https://cjj365.cc 是 html 的静态文件,是用静态文件生成器生成的。
    Ketteiron
    Ketteiron
    Jan 28❤️1
    37
    你应该更直接地表述这个工具到底解决了什么场景下的问题。
    什么时候有用?即使用 cookie 鉴权且后端设置了 SameSite=None; Secure 且需要远程访问本地运行的项目且需要保证开发环境与实际环境完全一致。
    这样就能劝退完全用不上的 99.99% 用户了。
    KellyAlsa
    KellyAlsa
    Jan 28
    38
    本地开发应该不需要搭建 https 的服务吧
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    39
    @Ketteiron 你比大多数评论者知道其中的微妙,不是远程访问的问题,在本地调试也是一样,在需要鉴权 cookie 的情况下,本地调试也需要 https.关于工具的用处,自认证证书的签发是很小一部分功能,主要是 public 证书签发。
    zh3256
    zh3256
    Jan 28 via Android
    40
    生产环境是否有 cors 问题,应该通过上线前端到端测试+灰度来避免,而不是你这种奇技淫巧。
    你的做法和本地 nginx 代理没啥优势,只要上线前没有实际环境校验过,谁能保证自己方案一定过呢?
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    41
    你根本不知道我们在说什么,问一下 @Ketteiron ,他知道。
    a132811
    a132811
    Jan 28
    42
    @zcf0508 我以前的做法,本地开发时直接用一键命令行的正向代理:证书、域名都本地生成、不侵入服务端  https://github.com/ahuigo/selfhttps
    explore365
    43
    用 openssl 或 mkcert 生成一个长期几十年的自签 CA 证书+localhost&127.0.0.1 域名证书,以后在每个测试的客户端安装这个 CA 自签证书即可。
    Ketteiron
    Ketteiron
    Jan 28❤️3
    44
    我来简单总结下吧。
    举个例子,本地使用 https:localhost ,浏览器需要一个受信任的证书,这里需要 mkcert 签发一个临时信任证书。
    如果从其他地方例如手机访问局域网,手机的浏览器会警告,因为它没有信任证书。
    那么"分布式" mkcert 如何提供证书,其实是服务端下发私有根证书。

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

    一般情况下 vite + vite-plugin-mkcert 就行了
    OP 的工具其实是解决了自动化复制 rootCA.pem 的操作。你说有用吧,确实有用,但我猜愿意用的没几个。
    chenluo0429
    chenluo0429
    Jan 28 via Android❤️4
    45
    遇到了一条河过不去怎么办?
    普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过
    动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去
    OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。
    chenluo0429
    chenluo0429
    Jan 28 via Android
    46
    遇到了一条河过不去怎么办?
    普通人:找负责的政府部门,建一座桥,最起码搭一座浮桥,大家都能过
    动手派:伐木自己做一条小船渡河,凑合着还能带两个人过去
    OP:你看我这里有一根绳子,还带个爪钩,你抛到对岸勾住,然后这边绑好在树上,就可以滑过去啦!你下次碰到另外的河,绳子都还可以用,船和桥就不行,这可比他们强多了。
    jianglibo
    jianglibo
    OP
    PRO
    Jan 28
    47
    @Ketteiron 评论里面算比较了解 CORS 的了,不过 cert-ctrl 不仅仅分发 CA ,也完成信任操作,比如 windows,linux,freebsd,macos,firefox 等等,也分发证书(电脑重装什么的不丢)。简单说,就是本来是命令行操作,机器之间复制的行为,变成 web 端的资源,然后通过 cert-ctrl 完成这种操作,比如证书更新之后执行脚本什么的。因为我自己的系统就有大量的证书,mysql ,redis ,rabbitmq ,mail server ,http 静态服务器,api 服务器等等,需要一个统一的管理和分发机制。
    AV1
    AV1
    Jan 28
    48
    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
    jianglibo
    OP
    PRO
    Jan 28
    49
    @AV1 实践. test and verify.
    patrickyoung
    50
    楼主完全不懂自己写的东西。

    AI 生成 /go/promotion

    @livid
    datou
    datou
    Jan 29
    51
    开发环境配上测试域名

    给测试域名签好 tls 证书

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

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

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

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

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

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

    大家可能不太会倾向于用这种东西的原因主要还是信任,信任这个东西不是说东西好用就够的,楼主的这个东西本质上就是自建一个 CA ,这种安全基础设施没有有公信力的第三方审计估计很少有人敢用。
    unco020511
    60
    @jianglibo #57 我懂你意思啊,还是那句话,用代理就可以很方便的解决,我在浏览器不会去访问 localhost,我访问的是域名,包括服务也是一样,访问的是真实域名,只不过通过代理打到你本地的项目上,这样都在一个域下,而且有真实的证书,你的生产环境是怎么访问的,在本地就是怎么访问
    jianglibo
    jianglibo
    OP
    PRO
    Jan 30
    61
    @unco020511 你不懂,根据我说的测试一下,你才正真了解 CORS
    unco020511
    62
    @jianglibo 你是真把我笑死了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3741 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 112ms · UTC 04:13 · PVG 12:13 · LAX 20:13 · JFK 23:13
    ♥ Do have faith in what you're doing.