繁体   English   中英

java.security.cert.CertificateException:找不到与IP地址xxxx匹配的使用者替代名称

[英]java.security.cert.CertificateException: No subject alternative names matching IP address x.x.x.x found

我有一个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-没有 与IP地址匹配的 使用者 替代名称SSLHandshakeException:没有使用者替代名称SSL证书服务器名称是如何解析的/我可以使用keytool添加替代名称吗? )但它们都不起作用(也许我在某处做错了。)

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

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字段中的信息,而是依赖于Subject Alternative Name

对于Chrome 58及更高版本,仅使用subjectAlternativeName扩展名(而非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

但是,这表明该站点不安全,因为证书无效。 我不确定是否由于此原因无法通过Java程序下载文件。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM