【问题标题】:java.security.cert.CertificateException: No subject alternative names matching IP address x.x.x.x foundjava.security.cert.CertificateException:找不到与 IP 地址 x.x.x.x 匹配的主题备用名称
【发布时间】:2019-09-23 12:15:48
【问题描述】:

我有一个 java 程序试图从一个 IP 地址下载一个文件。假设 IP 地址是 10.2.14.35。因此,该文件位于https://10.2.14.35/path/to/the/file/myfile.txt。我有以下用于下载该文件的功能:

public static void downloadFile(String uri, String localFileName) {
  try {
    URL url = new URL(uri);
    ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
    FileOutputStream fileOutputStream = new FileOutputStream(localFileName);

    fileOutputStream
        .getChannel()
        .transferFrom(readableByteChannel, 0 /* position */, Long.MAX_VALUE /* count */);

    fileOutputStream.close();
    readableByteChannel.close();
  } catch (IOException e) {
    throw new AgentException(ErrorProto.Type.kIOError, e.getMessage());
  }
}

并使用函数为:

downloadFile(" https://10.2.14.35/path/to/the/file/myfile.txt", "/tmp/myfile.txt")

我收到错误 java.security.cert.CertificateException: No subject alternative names matching IP address 10.2.14.35 found。我发现有人在 SO(JAVA - No subject alternative names matching IP address、SSLHandshakeException: No subject alternative names present、How are SSL certificate server names resolved/Can I add alternative names using keytool?)上提出了一些问题,但没有一个有效(或者我在某处做错了什么。)

从浏览器中,我尝试下载文件并下载。但是,这表明该站点不安全,因为证书无效。我不确定通过java程序下载文件失败是否是因为这个。在阅读时,我遇到了 cacerts 的概念,我必须让 JRE 明白连接到 10.2.14.35 是可以的。为此,我需要创建证书并将其导入 cacerts。我这样做了,但它没有用,因为也许我错过了一些东西。有人可以帮我指出错误吗?

【问题讨论】:

    标签: java ssl


    【解决方案1】:

    TLDR

    您看到的错误与名为Subject Alternative Name 的特定证书扩展有关,没有将10.2.14.35 指定为有效的IP 地址。

    该错误还表明证书 CA 已受信任。如果 CA 不受信任,则证书验证会更早失败并出现另一个错误,例如

    PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径


    由于我无权访问您的特定证书,我将尝试使用 example.com 的服务器证书进行说明。

    要查看证书,我将使用 openssl,但还有多种其他工具可用 - 例如,大多数浏览器都能够显示证书详细信息。

    我将删除我认为不需要说明我想要什么的输出

    $ openssl s_client -connect example.com:443 -showcerts | openssl x509 -noout -text
    [...]
    Subject: C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, OU = Technology, CN = www.example.org
    [...]
        X509v3 Subject Alternative Name: 
           DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net
    

    Subject 字段包含不同类型的信息,但 CN(通用名称)值为 www.example.com。以前,大多数或所有浏览器都使用它来验证证书是为浏览器连接到的服务器颁发的。然而,最近,Chrome(我认为是 Firefox)完全忽略了Subject 字段中的信息,而是完全忽略了relies on the Subject Alternative Name。

    对于 Chrome 58 及更高版本,只有 subjectAlternativeName 扩展, not commonName,用于匹配域名和站点证书。 证书使用者备用名称可以是域名或 IP 地址。如果证书没有正确 subjectAlternativeName 扩展,用户得到一个 NET::ERR_CERT_COMMON_NAME_INVALID 错误让他们知道 连接不是私有的。

    因此,您的错误源于10.2.14.35 提供的服务器证书不包含您要连接的IP 地址。使用 openssl 查看证书,服务器提供的证书必须至少有一个Subject Alternative Name,并且它至少需要包含IP Address:10.2.14.35。构建的最小示例看起来像这样。

    $ openssl s_client -connect 10.2.14.35:443 -showcerts | openssl x509 -noout -text
    [...]
    Subject: CN = 10.2.14.35
    [...]
        X509v3 Subject Alternative Name: 
            IP Address:10.2.14.35
    

    【讨论】:

      【解决方案2】:

      但是,这表明该站点不安全,因为证书无效。我不确定是不是因为这个原因导致无法通过java程序下载文件。

      虽然您没有提供浏览器的详细错误消息,但它抱怨的原因可能与 Java 说证书无效的原因相同,即因为 IP 地址不包含在证书的主题备用名称扩展中 (必须作为类型 IP 地址而不是 DNS 给出)。唯一的区别是您可以通过单击使浏览器忽略此错误,而您需要调整程序才能忽略该错误。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-17
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多