跳到主要内容
ecdsa.com
Node.js tls / https / fetchNode.js crypto 模块

错误信息

certificate has expired

也可能输出为

  • code: 'CERT_HAS_EXPIRED'
  • CERT_HAS_EXPIRED

所有 Node.js 版本中的消息文本都相同;使用 fetch() 时,它会作为“TypeError: fetch failed”的原因出现,npm 打印的是“npm error code CERT_HAS_EXPIRED”。尚未生效的证书则会产生 CERT_NOT_YET_VALID。

Node.js tls / https / fetch — code CERT_HAS_EXPIRED (OpenSSL X509_V_ERR_CERT_HAS_EXPIRED, 10)

含义

按这台机器的时钟,Node.js 构建的证书链中有一张证书已超过其 notAfter 日期。通常是服务器自己的证书;也可能是服务器仍在发送的中间证书,或者旧版 Node.js 内置的过时根证书列表中的某个根证书。Node.js 报告的消息是“certificate has expired”,代码为 CERT_HAS_EXPIRED。

原因

修复方法

  1. 1.

    查看服务器所提供证书的日期

    在不验证的情况下连接一次,只为读取证书:valid_to 和 authorizationError 会显示是哪张证书过期了。不要通过这个连接发送数据。

    js
    // Read the dates of the served certificate (inspection only, nothing is sent)
    import tls from "node:tls";
    
    const socket = tls.connect({ host: "api.example.com", port: 443, servername: "api.example.com", rejectUnauthorized: false }, () => {
      const cert = socket.getPeerCertificate();
      console.log(cert.subject.CN, cert.valid_from, "->", cert.valid_to, "authorized:", socket.authorized, socket.authorizationError);
      socket.end();
    });
  2. 2.

    续期并重新加载服务器证书

    通过 ACME 客户端或 CA 续期,重新加载每个终止 TLS 的进程,然后从网络一侧确认新的过期时间。

    bash
    sudo certbot renew && sudo systemctl reload nginx
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -noout -enddate
  3. 3.

    升级旧环境中的 Node.js

    如果服务器证书对其他客户端来说是有效的,问题很可能出在旧版 Node.js 的根证书列表上;升级到仍在维护的版本即可更新内置的根证书。

    bash
    # Node.js bundles its root list: old releases carry old (or expired) roots
    node -v
    node -p "require('tls').rootCertificates.length"

相关错误

浏览完整的签名错误库