跳到主要内容
ecdsa.com
Java (JSSE HostnameChecker)Java

错误信息

No subject alternative DNS name matching api.example.com found.

也可能输出为

  • javax.net.ssl.SSLHandshakeException: (certificate_unknown) No subject alternative DNS name matching api.example.com found.
  • java.security.cert.CertificateException: No subject alternative DNS name matching api.example.com found.

其中的主机就是你 URL 中的主机。JDK 21 和 25 会在前面加上 TLS 告警:“(certificate_unknown) No subject alternative DNS name matching … found.”。完全没有 SAN 扩展的证书,或者使用 IP 地址的 URL,则会分别报出“No subject alternative names present”和“No subject alternative names matching IP address … found”。

Java (JSSE HostnameChecker) — java.security.cert.CertificateException inside SSLHandshakeException

含义

证书链是可信的,但 Java 的主机名检查(HTTPS 端点识别)在证书的主题备用名称(SAN)扩展中没有找到与 URL 中主机匹配的 DNS 条目。消息中会给出 Java 要连接的主机。由于证书带有 SAN 扩展,Java 不会考虑它的通用名称。

原因

修复方法

  1. 1.

    列出证书包含的名称

    用 openssl 或 keytool -printcert -sslserver 显示 SubjectAlternativeName 条目,再与 URL 对比。

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -ext subjectAltName
    # or with Java's own tool
    keytool -printcert -sslserver api.example.com:443 | grep -A3 SubjectAlternativeName
  2. 2.

    补上缺失的名称,重新签发证书

    申请时列出客户端使用的每一个 DNS 名称;keytool 的 -ext SAN=dns:…,dns:… 可以把它们加入 CSR。

    bash
    # Java keystores: request a certificate with every name in the SAN extension
    keytool -certreq -alias server -keystore server.p12 -ext "SAN=dns:api.example.com,dns:www.example.com" -file server.csr
  3. 3.

    使用证书中列出的名称连接

    保持主机名验证开启,改为修改 URL(以及名称解析);一律放行的 HostnameVerifier 等于取消了 TLS 本该提供的保护。

    java
    // Use the name in the certificate in the URL; resolve it to the address you need
    // (DNS, /etc/hosts or a custom resolver), instead of connecting by IP or alias.
    HttpRequest req = HttpRequest.newBuilder(URI.create("https://www.example.com/health")).build();

相关错误

浏览完整的签名错误库