如何借助 ACME、自动续期与零接触工作流实现证书管理自动化
证书过期持续导致拥有成熟基础设施团队的公司发生故障,而事后复盘很少归咎于缺失的 cron 任务。续期已经配置好了。它也运行了。服务还是挂了。配置续期看起来像是自动化证书管理,但真正的门槛更高:签发、部署、验证和告警都要在无人参与的情况下运行。留给人工的那一步,通常就是故障开始的地方。
时间点比以往任何时候都更重要。公共 TLS 证书的有效期正在按固定时间表缩短:2026 年 3 月起生效最长 200 天,2027 年将降至 100 天,2029 年将降至 47 天。今天还能容忍偶尔人工介入的续期流程,到那个节奏下将完全失效。
对于正在评估 SSL 证书管理与自动化的团队来说,这意味着四个具体部分:通过 ACME(Automatic Certificate Management Environment,自动证书管理环境)进行自动化签发、一种适合你基础设施的域名验证方法、同时能重载服务的续期,以及对客户端实际收到的证书的监控。
为什么手动证书管理会失败,而且即将失败得更快
你有一台运行 nginx 的服务器,使用一张 90 天有效期的证书。nginx 启动时,会从磁盘读取证书文件并把一份副本加载进内存;它向每个连接的客户端出示的就是这份内存中的副本。除非有什么东西告诉它重载,否则 nginx 不会再次读取该文件。
为了处理续期,有人添加了一个 cron 任务。它每天运行一次,检查磁盘上的证书还剩多少有效期,并在剩余不足 30 天时重新签发:
## 通过 cron 每天运行
days_left=$(cert_days_remaining /etc/nginx/certs/server.crt) # openssl x509 -enddate,解析后得到
if [ "$days_left" -lt 30 ]; then
issue-cert.sh # 将新的密钥和证书写入磁盘
fi
在第 60 天,任务触发。它把新证书写入磁盘并报告成功。但脚本中没有任何内容告诉 nginx 重载,所以 nginx 继续提供它在第 0 天加载的那份副本。现在存在两张证书:文件里是新的,内存里是原始的那张,距过期还有 30 天。
在第 90 天,原始证书过期,每个连接到该站点的客户端都会收到 certificate has expired。磁盘上的文件还有 60 天有效期。cron 任务每天都报告成功,而监控只盯着任务而不是站点本身,因此没有发现任何异常。
| 天数 | 磁盘上的文件 | nginx 内存中的副本 | 客户端看到 |
|---|---|---|---|
| 0 | 已签发,剩余 90 天 | 启动时加载,剩余 90 天 | 正常 |
| 60 | 已续期,剩余 90 天 | 原始证书,剩余 30 天 | 正常 |
| 90 | 剩余 60 天 | 原始证书,已过期 | certificate has expired |
续期证书和部署证书是两个独立的步骤。脚本处理了第一步,但从未尝试第二步;由于这套设置中没有任何东西检查第二步,失败一直不可见,直到它把网站搞挂的那一天。

常见的修复方法是再写一个脚本,监视证书文件并在其变化时重载 nginx。这可行。但它也意味着每台主机上现在都运行着一个续期脚本、一个文件监视器、与 CA 配合使用的账户密钥、证书私钥,有时还有一个 DNS API Token,全部靠手工维护。主机之外的任何东西都不知道这张证书的存在,而当 cron 任务本身悄悄死掉时,也没有任何东西会告警。

certbot 的 deploy hook 是同一思路更干净的版本,因为它只在续期真正成功之后才运行。无论哪种方式,手动证书管理都是一系列步骤,每一步都依赖某个人或某个手写的脚本:
- 知道证书的存在。
- 注意到到期日临近。
- 运行续期。
- 部署结果。
- 确认服务已加载新证书。
任何一步都可能悄悄失败,而且因为没有任何东西检查客户端实际收到的证书,第一个告警就是故障本身。你以前一定见过类似的事情,甚至当过受害者。细节各不相同,但结果看起来一样:
- Microsoft Teams 在 2020 年 2 月因身份验证证书过期未续期而宕机数小时。
- 2018 年 12 月,爱立信核心网络软件中一张过期的证书导致移动数据中断,影响 O2 和 SoftBank 数千万用户。
- Starlink 在 2023 年 4 月全球断服数小时,SpaceX 将其归因于地面站证书过期。
这些是单张证书的故事。日常版本是规模问题。Keyfactor 的 2024 PKI 与数字信任报告指出,平均每个组织内部约有 80,000 张受信任的证书,而大多数受访者说不清自己到底有多少张。哪怕只有几百张证书,分属不同团队、在不同日期到期,总有某条链路的某一步接近失败,而五个手动步骤经不起这么多次的重复执行。
同一份报告还指出,大多数组织每年都会发生多起与证书相关的事故,识别每次故障平均需要约 2.6 小时,修复还需要另外 2.7 小时。CyberArk 的证书故障研究发现,72% 的组织在过去 12 个月里至少发生过一起此类事故。
手动续期能撑到现在,是因为 398 天的证书留出了很大的容错空间。但这个空间正在按已公布的时间表消失。2025 年 4 月,CA/Browser Forum 通过了投票 SC-081v3,这是 Apple 提出的一项提案,分阶段限制公共受信任 TLS 证书的有效期:
| 生效日期 | 最长有效期 | 最长域名验证复用期 |
|---|---|---|
| 2026 年 3 月 15 日 | 200 天 | 200 天 |
| 2027 年 3 月 15 日 | 100 天 | 100 天 |
| 2029 年 3 月 15 日 | 47 天 | 10 天 |
域名验证复用是指 CA 可以在多长时间内继续信任你控制某个域名的同一次证明。一旦降到 10 天,正常的 47 天续期周期意味着几乎每次签发都需要全新的验证,因此证明域名控制权必须与续期和部署一起实现自动化。
这已经在落地中:
- Google 的 Chrome Root Program 早在 2023 年就在其 Moving Forward, Together 路线图中提出了 90 天上限,而行业投票走得更远。
- Let's Encrypt 默认证书将在 2027 年 2 月降至 64 天,2028 年 2 月降至 45 天,域名验证复用期缩短至 7 小时,且六天证书已经全面可用。
Let's Encrypt 还在 2025 年 6 月停止发送到期通知邮件,因为自动化已经让它们变得多余。
算一算 47 天的账。按完整有效期计算,一年大约续期 8 次。不过客户端会提前续期,若在生命周期的三分之二处续期,则更接近十二个签发周期。对 100 张证书而言,相当于整个集群每七到八小时就有一次签发。
这些限制适用于公共受信任的证书,而内部 CA 可以签发你配置的任意有效期。虽然内部证书和公共证书通常使用不同的签发者和验证方法,但围绕它们的自动化、清单、归属和监控应该保持一致。
ACME 协议如何工作
ACME,即 Automatic Certificate Management Environment(自动证书管理环境),是一种允许软件在无人参与的情况下自动获取证书的协议。这个名字是字面意思:它为客户端和 CA 提供了一个共享的、自动化的证书验证与签发管理环境。它起源于 Let's Encrypt 和 Internet Security Research Group,IETF 于 2019 年将其标准化为 RFC 8555。
ACME 客户端和服务器通过 HTTPS 交换 JSON。客户端获取目录和一个 nonce 之后,它发送的每个操作都用其账户密钥签名:
- 客户端获取 CA 的端点 URL 目录,并创建一个与其生成的密钥对绑定的账户,或者使用它已有的账户。
- 它创建一个订单,列出想要包含在证书中的名称。
- CA 为每个名称返回一个授权,指明它接受的挑战类型,客户端为每个仍需验证的名称完成一个挑战。
- 所有名称获得授权后,客户端提交 CSR(certificate signing request,证书签名请求)并下载签好的证书链。
- 客户端的安装插件或部署Hook把证书放到服务期望的位置,并确保服务加载了它。
最后一步位于协议之外,这正是它常常被跳过的原因。

续期就是走同样流程的另一个订单。如果之前的验证仍然有效,CA 可以复用它;否则,客户端再次证明控制权。无论哪种方式,替换证书都必须像原始证书一样被部署。
交互双方都没有什么特殊之处。针对 Let's Encrypt 可用的 certbot 调用,同样适用于任何 ACME directory URL,包括私有 CA 前面的那个,因此切换 CA 只是一个 URL 变更,而不是工具迁移。当某个 CA 出事故或你的需求发生变化时,这一点很重要。
这也意味着客户端是一个已被解决的问题。certbot 覆盖大多数 Linux 主机,acme.sh 和 win-acme 覆盖只有 shell 的机器和 Windows,Caddy 和 Traefik 则内置了客户端,所以在这些服务器上,证书无需任何单独的工具就能到位。
另一方面,现在每个主要的公共 CA 都运行着 ACME 服务器,包括 Let's Encrypt、ZeroSSL、Google Trust Services、DigiCert 和 Sectigo,私有 CA 平台也是如此。私有 CA 多出的一步是身份:ACME 账户本身是匿名的,因此 CA 会给你一个密钥 ID 和密钥,称为 external account binding(EAB),客户端在注册时出示一次,把账户绑定到你的客户账户或证书 profile 上。
HTTP-01 vs DNS-01:选择验证挑战
每种挑战都在回答来自 CA 的同一个问题:证明你控制这个域名。两种主要类型的挑战区别在于你把证明放在哪里。HTTP-01 把它放在你的 Web 服务器上,DNS-01 把它放在你的 DNS 记录里。
HTTP-01:在端口 80 上提供一个 Token
CA 给客户端一个 Token,客户端把它放在 http://<domain>/.well-known/acme-challenge/<token> 上,然后 CA 来取。规范将挑战固定在端口 80,所以这个端口必须能从互联网访问。

HTTP-01 是最容易运维的挑战。任何 Web 服务器都能提供一个静态文件,也不涉及 DNS 访问。托管平台也是这样为客户域名获取证书的:当域名指向它们的服务器时,它们可以替该域名应答挑战。约束条件是:不支持通配符证书,端口 80 必须保持开放,而且在负载均衡池中,无论 CA 恰好连到哪个后端,Token 都必须存在于那里。
DNS-01:发布一条 TXT 记录
客户端在 _acme-challenge.<domain> 发布一条包含 Token 哈希值的 TXT 记录,然后 CA 查询 DNS。提供服务的主机是什么完全无关紧要,这使得 DNS-01 成为通配符证书、不接受互联网入站连接的内部服务以及 CDN 后面的一切的最佳选择。

代价是凭证管理。完成挑战的机器需要对 DNS 服务商的 API 访问权限,而一个能创建 DNS 记录的 Token 通常也能改变域名的指向。把凭证的范围限制到服务商允许的最小程度,或者通过 CNAME 把 _acme-challenge 委托到一个只为验证而存在的独立 zone,这样这个 Token 就管不到其他任何东西。DNS 传播还会带来延迟,所以客户端会在请求 CA 验证之前等待并重试。
使用 certbot 和 Cloudflare 时,这归结为一个插件和一个凭证文件,其中保存着一个仅限单个 zone DNS 编辑权限的 API Token:
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.example.com" -d example.com
插件发布 TXT 记录,等待传播,并在验证完成后删除记录。每个主流 DNS 服务商都有等价物。
适合大多数团队的默认方案:能在端口 80 上应答的公共 Web 服务器用 HTTP-01,其余一切用 DNS-01。通配符、内部主机和多服务器集群都指向 DNS-01,而凭证问题值得在第一张证书签发之前就回答清楚,而不是在第一次事故之后再回答。
| HTTP-01 | DNS-01 | |
|---|---|---|
| 证明所在位置 | 你的 Web 服务器上,端口 80 | 一条 DNS TXT 记录 |
| CA 必须能够访问 | 你的服务器,从互联网 | 仅公共 DNS |
| 通配符证书 | 否 | 是 |
| 内部或防火墙后的主机 | 否 | 是 |
| 需要保护的凭证 | 无 | DNS 服务商 API Token |
| 设置 | 在任何公共 Web 服务器上都轻而易举 | 需要一个带 API 的 DNS 服务商 |
第三种选项 TLS-ALPN-01 在端口 443 的 TLS 握手过程本身中证明控制权。它适用于端口 80 被封锁的环境,不支持通配符,客户端支持也更薄弱,所以把它当作前两者都不适用时的备选方案。
cert-manager:Kubernetes 上的自动化证书
在 Kubernetes 内部,cert-manager 是证书管理自动化的标准工具,它的工作方式与 Kubernetes 中其他一切的工作方式相同:你声明你想要的东西,控制器让它成真(并保持成真)。
Issuer 或 ClusterIssuer 说明证书从哪里来,Certificate 说明你想签发什么。其余工作由控制器完成:运行 ACME 交互,把密钥和证书链存到你 Ingress 或 pods 引用的 Secret 中,并按计划续期。

一个面向 Let's Encrypt 的集群级 issuer 如下所示:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ops@example.com
privateKeySecretRef:
name: letsencrypt-account-key
solvers:
- http01:
ingress:
ingressClassName: <your-maintained-ingress-class>
大多数工作负载根本不需要显式的 Certificate 资源。给 Ingress 加上 cert-manager.io/cluster-issuer: letsencrypt-prod 注解,并提供一个包含主机名和 secretName 的 tls 块,cert-manager 就会自行签发和续期这些证书。这样一来,续期无需人工步骤就能到达客户端。
默认情况下,cert-manager 在证书生命周期过了三分之二后续期:90 天的证书在第 60 天,47 天的证书在第 31 天。renewBefore 字段可以覆盖默认值。
因为 cert-manager 说的是标准 ACME,server 字段接受任何 directory URL,issuer 规范中的 externalAccountBinding 则覆盖要求 EAB 的 CA。无论背后的 CA 是 Let's Encrypt 还是私有 CA,同样的 manifest 结构都适用。
自动续期工作流的剖析
在 Kubernetes 之外,续期自动化有四个部分:
- 决定何时续期的触发器
- 续期本身
- 让服务加载新证书的部署步骤
- 发现其中任何环节失败的监控

certbot 开箱即用地处理触发器。安装它会注册一个 systemd 定时器(旧系统上是 cron 条目),每天在随机时间运行两次 certbot renew,而且该命令只作用于临近到期的证书。certbot renew --dry-run 会针对 staging 环境做一次完整的演练续期,让你可以在信任它用于生产之前先验证设置。
部署是续期脚本最常跳过的步骤。磁盘上续期后的文件在服务重载之前毫无作用,所以每次续期都需要附加一个Hook:
certbot renew --deploy-hook "systemctl reload nginx"
certbot 还会在每次成功续期后运行 /etc/letsencrypt/renewal-hooks/deploy/ 里的所有内容,这是放置重载逻辑更好的地方:放在那里的Hook无论续期最终如何被运行都会触发,而命令行标志只有在有人记得传参时才生效。同样的思路适用于 HAProxy、Apache 或其他任何把证书加载进内存的东西。
然后在信任它之前,手动验证整条路径一次:
## 记录当前提供的证书
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -serial
## 测试续期并运行已配置的 deploy hook
sudo certbot renew --cert-name example.com --dry-run --run-deploy-hooks
## 可选的一次性真实测试:这会消耗真实的签发额度
sudo certbot renew --cert-name example.com --force-renewal
## 重新运行第一条命令:出现新序列号说明续期和重载都成功了
在 dry run 期间,所提供证书的序列号按设计保持不变,因为Hook是对线上证书而不是 staging 证书运行的。序列号只在强制续期之后才会变化,如果没变,说明重载从未发生。在测试中发现这一点,胜过在悄无声息的续期一个月之后才发现。
监控服务实际出示的证书,而不是磁盘上的文件。一个连接端点、读取所提供证书的到期时间并在达到阈值时告警的探针,能一次性捕获所有失败模式:从未运行的续期、运行了但失败的续期,以及成功但没有重载的续期。
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate
你应该把一次失败的续期当作事故来对待,因为从失败到到期日之间的时间是修复它的唯一窗口。也不要等着 CA 来提醒你:Let's Encrypt 已经在 2025 年停止发送到期邮件了,所以告警要靠你自己搭建。
零接触续期:当服务器包办一切
零接触证书管理意味着没有人编写触发器、Hook或监控,因为提供 HTTPS 的 Web 服务器或代理处理整个生命周期。

Caddy 是最清晰的例子。Automatic HTTPS 是它的默认行为:给它一个域名,它就会获取证书,在生命周期大约剩三分之一时续期,并在不断开连接的情况下换上新证书。Traefik 内置了 ACME 解析器,最近的 HAProxy 版本也加入了原生 ACME 支持,所以这种方式现在已经覆盖了代理层的大部分。
云服务商提供托管版本。AWS Certificate Manager 自动化 AWS 中的 SSL 证书管理:它签发公共证书、自动续期,并将续期证书部署到负载均衡器、CloudFront 和 API Gateway,你这边不需要任何机制。Google 托管证书和 Azure App Service 托管证书在其各自平台内以同样的方式工作。
限制在于:Caddy 管理的是那台 Caddy 服务器上的证书,ACM 管理的是挂在 AWS 服务上的那些,两者都无法告诉你其他任何东西的情况。这两种方式也都是优先为公共 TLS 构建的,来自你自己私有 CA 的证书大多不在它们的管辖范围内。横跨 VM、Kubernetes、多个云和内部服务的资产,需要某种不受限于单台机器或单一平台的东西来提供同样的免维护行为。
如何用 Infisical 自动化证书管理
Infisical 的证书管理器把签发、续期、部署和可见性作为一个系统来运行:密钥永不离开平台的私有 CA、设定可签发内容规则的证书 profile(允许的名称、有效期、密钥类型)、通过 API 或 ACME 发起的证书请求,以及带有到期告警和吊销功能的清单,覆盖所有已签发的证书。
创建一个私有 CA 和一个证书 profile 只需在仪表板中花几分钟,外部 CA 也可以签发 profile,因此公共证书和私有证书共享同一个清单。
有两种使用方式:在每个服务旁边运行 Infisical 的 agent,或者把你已有的 ACME 客户端直接指向 Infisical。

Agent 路线:每台主机一个 YAML 文件
Infisical agent 与你的服务一同运行,以机器身份进行认证,并对证书进行端到端管理。它的配置取代了手写的续期脚本、重载监视器以及存储在主机上的任何签发凭证。以下是 Infisical 当前 applications 风格的配置:
version: v1
## Infisical 服务器配置
infisical:
address: "https://app.infisical.com" # Infisical 实例的 URL(例如 https://app.infisical.com、https://eu.infisical.com、https://your-self-hosted-instance.com)
retry-strategy:
max-retries: 3
max-delay: "5s"
base-delay: "200ms"
## Infisical 认证配置
auth:
type: "universal-auth" # 要使用的认证方式(例如 universal-auth、kubernetes-auth、azure-auth、gcp-id-token、gcp-iam、aws-iam)
config:
client-id: "your-client-id"
client-secret: "your-client-secret"
## 证书配置
certificates:
- profile-name: "prof-web-server-12345"
project-slug: "my-project-slug"
attributes:
common-name: "api.example.com"
alt-names:
- "api.example.com"
- "api-v2.example.com"
key-algorithm: "RSA_2048"
signature-algorithm: "RSA-SHA256"
key-usages:
- "digital_signature"
- "key_encipherment"
extended-key-usages:
- "server_auth"
ttl: "30d"
lifecycle:
renew-before-expiry: "14d" # 在到期前 14 天续期
status-check-interval: "6h" # 每 6 小时检查一次证书状态
file-output:
private-key:
path: "/etc/ssl/private/api.example.com.key"
permission: "0600"
certificate:
path: "/etc/ssl/certs/api.example.com.crt"
permission: "0644"
chain:
path: "/etc/ssl/certs/api.example.com.chain.crt"
permission: "0644"
post-hooks:
on-issuance:
command: "systemctl reload nginx"
timeout: 30
on-renewal:
command: "systemctl reload nginx && logger 'Certificate renewed'"
timeout: 30
infisical cert-manager agent --config agent.yaml 启动整个循环。agent 根据 profile 请求证书,把密钥、证书和链写到服务期望的位置,在配置的阈值处续期,并触发 post-hook 让服务重载。CA 密钥留在 Infisical 中,主机持有的凭证只能请求证书而不能做别的,agent 获取的每一张证书都会出现在中央清单中。
验证它只需要几分钟,而不是等待两个月才能迎来第一次真正的轮换。对一个允许短生命周期的测试 profile,把 ttl 和 renew-before-expiry 设为几分钟,观察所提供证书的序列号在每个周期都发生变化且请求持续成功,然后再恢复生产值。
| 手写组件 | Agent 对应物 |
|---|---|
| 每天检查到期时间的续期 cron | lifecycle.renew-before-expiry |
| 重载服务的文件监视器 | post-hooks.on-renewal |
| 主机上的签发脚本加上 CA 密钥或 DNS Token | 限定于单个证书 profile 的机器身份 |
| 记录什么东西在哪里的电子表格 | 带到期告警的中央清单 |
有一件事 agent 替你做不到:如果 profile 由私有 CA 签发,根证书必须到达每一个将要连接的客户端信任库。链文件让 nginx 发送叶子证书和中间证书,但对让客户端信任根证书毫无作用。
ACME 路线:保留你已有的客户端
每个证书 profile 还可以暴露一个 ACME directory URL,这让 Infisical 成为一台 ACME 服务器。用该 profile 的 EAB 凭证把任何标准客户端指向它,工作流程与 Let's Encrypt 完全相同,只是签发者是你的私有 CA:
sudo certbot certonly \
--standalone \
--server "<ACME Directory URL>" \
--eab-kid "<EAB Key Identifier>" \
--eab-hmac-key "<EAB Secret>" \
-d api.example.com \
--email admin@example.com \
--agree-tos \
--non-interactive \
--deploy-hook "systemctl reload nginx"
从这里开始由 certbot 自己的定时器处理续期,deploy hook 在每次续期时再次运行。验收测试与任何 ACME CA 相同:强制续期一次,确认所提供证书的序列号发生变化。
这里同样适用。fullchain.pem 覆盖了 nginx 发送的内容,而把私有根证书分发到客户端信任库仍然是你自己的事。
中心化消除了什么
差异在集群规模下显现出来。没有控制平面时,20 台主机意味着:
- 20 个需要配置和打补丁的 ACME 客户端或续期脚本
- DNS API Token 分发到每一台应答 DNS-01 挑战的机器
- 各团队自行追踪签发了什么、何时签发
- 没有单一的地方可以吊销证书或查看哪些证书本月到期
有了控制平面,签发策略保存在证书 profile 里,续期和部署只是两行 agent 配置或一个现成的 ACME 客户端,当需要人工介入时,到期告警会路由到 Slack、PagerDuty 或 webhook。而被遗忘的证书也能被发现,因为发现扫描会找出没人登记的东西。
从清单开始,以零接触结束
一个可行的顺序如下:
- 盘点你拥有的证书。 用
nmap --script ssl-cert扫描你的地址空间,找到当前所有提供 TLS 的东西;在你的域名上搜索 crt.sh,可以看到公共 CA 为它们签发的每一张证书。记录到期时间、签发者,以及目前负责续期每一张证书的人。 - 给每张证书接上 ACME 并附带 deploy hook。 主机上用带
--deploy-hook的 certbot,Kubernetes 中用ClusterIssuer加 ingress 注解,以及在可以更换代理的地方用 Caddy 或 Traefik。当每台主机的 dry run 都通过、并且一次强制测试续期到达了客户端时,你就完成了。 - 从外部监控所提供的证书。 运行一个定时探针,从在线端点读取到期时间——无论是 Prometheus blackbox exporter 的
probe_ssl_earliest_cert_expiry指标,还是 cron 里的 openssls_client检查——并在续期失败或剩余有效期低于阈值时触发告警。 - 在规模增长时中心化。 触发时机是:当你自己运行 ACME 客户端的主机多到不想再手工打补丁、DNS Token 出现在不止一台机器上,或者出现了第一个需要私有 CA 的内部服务。到那时,把签发策略、续期和告警移到一个地方,日常证书工作就会归零。
200 天的上限已经生效,47 天将于 2029 年 3 月到来。到那时,每张公共证书每年大约续期八次,只有当签发、续期、部署和监控都在无人参与的闭环中运行时才可行。无论是单台主机上的 certbot 加 deploy hook,还是用 Infisical 在整个集群上运行生命周期,构建它的最佳时机就是证书还有 200 天有效期的现在。
- 原文链接: infisical.com/blog/autom...
- 鸿途知科网 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
鸿途知科网
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。