java - Web 服务客户端 - 带有 keystore

标签 java keystore webservice-client

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

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

我的代码:

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文件,如何创建与此证书文件的连接?

最佳答案

“无法找到有效的证书路径”(在 SSL/TLS 握手期间)与您的 keystore 无关 - 这意味着服务器证书不会针对您的信任库进行验证,因为您将 null 作为第二个参数传递给 context.init是JRE的默认值,即sysprop javax.net.ssl.trustStore指定的文件如果另外设置 JRE/lib/security/cacerts (或 .../jssecacerts 如果存在)。

该服务器正在使用根证书 Gemalto Business Root Certificate Authority 下颁发的证书它不包含在 Oracle Java 包提供的 cacerts 中,也不包含在我所知道的任何其他已建立的信任库中,并且公共(public)透明度日志中不知道它(根据 https://crt.sh )。 SoapUI,大概是因为它被设计为开发、测试和调试工具,会忽略无效或可疑的证书,但浏览器或 curlwget除非您系统上的信任库已被修改或出现其他异常,否则对该 URL 的访问应该会失败。 奥托openssl s_client它主要也是一个调试工具报告错误但仍然建立连接。

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

获得证书的简单方法是:

  • openssl s_client -showcerts -connect host:port </dev/null (在 Windows <NUL: 上)-- 使用端口 443;现在许多服务器需要服务器名称指示扩展(又名 SNI),对于低于 1.1.1 的 OpenSSL,您必须添加 -servername host提供它,但该服务器不提供。这会为来自服务器的每个证书输出一个 PEM block ,每个证书之前的标签显示 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 block ,因此,如果您还没有从我的上一篇文章中了解顺序,则必须解码每个 block 以找出哪个是哪个,或者只是进行实验,直到找到正确的 block 。

无论哪种情况,都获取所需的 PEM block 并将其放入文件中,然后执行

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

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

关于java - Web 服务客户端 - 带有 keystore ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58397803/

相关文章:

java - Eclipse 中缺少非必需库的必需库

java - 两个移动设备之间的安全连接 : SSL key not 'private'

java - 无法使用 wsdl2java 从 wsdl 生成 java 类

java - myeclipse 工作台中的嵌套工作集

java - 在记事本中而不是在控制台上显示程序输出?

android - 当我尝试运行项目时,signingConfig.storeFile 不存在

java - 为什么我在 ~/.android 文件夹中没有 debug.keystore(对于 mac)?

r - 在 R 中使用 Web 服务

java - 使用php调用web服务

java - 如何在 Android 上播放变化的 MIDI - jetPlayer