【问题标题】:web-service client - with keystoreWeb 服务客户端 - 带有密钥库
【发布时间】:2019-10-15 15:09:49
【问题描述】:

我需要创建一个带有密钥库的 Web 服务客户端。但这是错误:

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

我的代码:

private SSLSocketFactory getFactory() throws Exception {

          File pKeyFile = new ClassPathResource("jks/dex-client-issuer-wss.jks").getFile();

          KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX");
          KeyStore keyStore = KeyStore.getInstance("JKS");

          InputStream keyInput = new FileInputStream(pKeyFile);
          keyStore.load(keyInput, pass.toCharArray());
          keyInput.close();

          keyManagerFactory.init(keyStore, pass.toCharArray());

          SSLContext context = SSLContext.getInstance("TLS");
          context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());

          return context.getSocketFactory();
    }

这是http连接:

URL url = new URL("https://dexxis-demo1.gemalto.com/DEX/communication/issuer-interface");
        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
        con.setSSLSocketFactory(getFactory());

我只有一个与soap ui一起使用的dex-client-issuer-wss.jks文件,我该如何创建与这个证书文件的连接?

【问题讨论】:

  • 您确定找到了 jks 文件吗?
  • 嗨,是的,我确定文件是正确的并且文件类找到了它

标签: java keystore webservice-client


【解决方案1】:

'无法找到有效的证书路径'(在 SSL/TLS 握手期间)与您的密钥库无关——这意味着 server 证书不会针对您的 truststore,因为您将 null 作为第二个参数传递给 context.init,所以它是 JRE 的默认值,如果设置为 javax.net.ssl.trustStore,则它是 sysprop 指定的文件 JRE/lib/security/cacerts(或 .../jssecacerts,如果存在)。

该服务器正在使用根证书Gemalto Business Root Certificate Authority 下颁发的证书,该证书不包含在随 Oracle Java 软件包提供的 cacerts 或我知道的任何其他已建立的信任库中,并且公共透明度日志不知道(根据 @ 987654321@)。 SoapUI,大概是因为它被设计为开发、测试和调试工具,会忽略无效或可疑的证书,但是除非您系统上的信任库,否则该 URL 上的浏览​​器或 curlwget 应该会失败已被修改或以其他方式异常。 OTOH openssl s_client 这也是一个主要的调试工具报告一个错误,但无论如何都会建立连接。

如果您确实想信任该 CA 或其(两个)中间体之一,或者无论如何要信任该站点,您需要在您的信任库中拥有适当的证书。 通常的做法是信任根 CA 证书,但 Java 支持使用链中的任何证书(包括 EE 证书)作为锚点。由于您已经在创建自己的上下文和密钥管理器,因此您不妨创建自己的信任管理器,而不是修改 JRE 默认值,这(通常)依赖于平台/环境,有时很棘手。您可以获取所需的证书并将其放入单独的密钥库文件(见下文),加载并使用它来创建信任管理器。或者,由于您已经拥有自己的密钥+证书的密钥库文件,Java 支持在同一文件中同时拥有一个或多个 privateKey 条目一个或多个trustedCert 条目,因此您可以将他们的证书添加到您现有的 JKS 中,并在 TrustManagerFactory 中使用相同的 KeyStore 对象,就像 KeyManagerFactory 为您的上下文创建 trustmanager 数组一样。

获取证书的简单方法是:

  • openssl s_client -showcerts -connect host:port </dev/null(在 Windows 上 <NUL:)——使用端口 443;现在许多服务器都需要服务器名称指示扩展(又名 SNI),对于低于 1.1.1 的 OpenSSL,您必须添加 -servername host 来提供它,但此服务器不需要。这将为来自服务器的每个证书输出一个 PEM 块,每个之前的标签显示 s: (subjectname)i: (issuername)。请注意,在第一个证书(根据需要是 EE 证书)之后,此服务器以自上而下的顺序而不是自下而上的顺序发送 CA 证书。这在技术上违反了 RFC 5246(或更早的 4346 或 2246); TLS1.3 的 RFC 8446 允许它,因为它已经是一个通用扩展,Java JSSE 尤其支持它。

  • keytool -printcert -rfc -sslserver host -- 也支持host:port,但默认为 443,这对你来说没问题。这仅输出 PEM 块,因此如果您还没有从我的上一个项目中知道订单,您将不得不对每个项目进行解码以找出哪个是哪个,或者只是试验直到找到正确的一个。

在任何一种情况下,获取所需的 PEM 块并将其放入文件中,然后执行

keytool -importcert -keystore jksfile -alias somealias -file thecertfile

somealias要求在文件中是唯一的(如果将其放在自己的文件中,这很简单)并且不区分大小写(通常为小写),但应该是描述性的或助记符, 并且仅在可能的情况下使用字母数字。然后像上面一样使用生成的文件。

【讨论】:

    猜你喜欢
    • 2011-03-30
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    相关资源
    最近更新 更多