Java Web Start应用程序中的HttpsUrlConnections不信任添加到Java控制面板的SSL认证

Java Web Start应用程序中的HttpsUrlConnections不信任添加到Java控制面板的SSL认证,java,https,jersey,jax-rs,java-web-start,Java,Https,Jersey,Jax Rs,Java Web Start,简短版本:是否有一种方法可以使在Java Web Start应用程序中启动的HttpsUrlConnections信任Java控制面板中安装的证书,或者是否有另一种用户友好的方法(不涉及命令行)将某些证书添加到此类连接使用的信任存储中 我们的JavaWebStart应用程序访问多个Web服务(通过标准配置中的JAX-RS/Jersey,最终使用HttpsUrlConnection的JWS特定实现)。有时,由于不受信任的证书,这些证书会引发SSL证书验证错误: sun.security.provi

简短版本:是否有一种方法可以使在Java Web Start应用程序中启动的HttpsUrlConnections信任Java控制面板中安装的证书,或者是否有另一种用户友好的方法(不涉及命令行)将某些证书添加到此类连接使用的信任存储中

我们的JavaWebStart应用程序访问多个Web服务(通过标准配置中的JAX-RS/Jersey,最终使用HttpsUrlConnection的JWS特定实现)。有时,由于不受信任的证书,这些证书会引发SSL证书验证错误:

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
发生这种情况有几个合理的原因:

  • 在我们的测试环境中,站点证书由我们的内部CA颁发,默认情况下JRE不信任该CA
  • 我们的一些用户有“SSL终止”代理,这是web代理的一个别致的名称,用于解密SSL流量并使用不同的证书将其转发。从应用程序的角度来看,这与中间人攻击无法区分
  • 在升级生产中的服务器后,我们通过在将其添加到负载平衡器之前从各个服务器启动应用程序来测试应用程序;这些服务器的证书也由我们的内部CA签署
目前,我们的代码能够识别这些错误,向用户显示措辞严厉的警告,并且如果用户希望继续,可以安装一个“全部接受”默认信任管理器和主机名验证器到HttpsUrlConnection,以完全绕过SSL验证,这在其他地方有广泛的记录。这是一个麻烦的解决方案,很难维护,它出现在应用程序的每次执行中,它会掩盖其他错误(我们连接到多个站点),感觉就像是重新发明轮子

另一种方法是使用keytool将不受信任的CA证书添加到JVM的信任存储中。这不是一个非常用户友好的解决方案,因为它涉及大量的命令行黑客,并且在每次JRE升级后都会被清除


我希望将这些证书添加到Java控制面板也能实现同样的效果,但它似乎没有;尽管它在安装和启动应用程序时消除了Java Web Start警告,但从应用程序内部进行的HttpsUrlConnections仍然不信任这些证书,导致上述错误和自行生成的覆盖。

您面临的问题是JAX-RS不使用默认的
SSLContext
HostnameVerifier
。这实际上是一件好事,因为您可以通过编程方式为客户机连接设置它们,而不是让它使用全局连接。为此,您需要创建一个ClientBuilder,并将主机名验证器和sslcontext设置为您可以控制的内容

public Client buildUnsecureRestClient() throws GeneralSecurityException {
  SSLContext context = SSLContext.getInstance("TLSv1");
  TrustManager[] trustManagerArray = {
      ...
  };
  context.init(myKeyManagers, trustManagerArray, new SecureRandom());
  return ClientBuilder.newBuilder()
    .hostnameVerifier(myhostnameverifier)
    .sslContext(context)
    .build();
}


通过将SSLContext设置为包含您自己的密钥管理器,您可以通过编程方式构建密钥管理器。我有一个使用该技术的示例,但是您可以实现X509KeyManager来提供密钥。X509TrustManager有点棘手,我建议您使用目标JDK附带的一个,即使它会将您锁定到Oracle的sun.security.ssl.X509TrustManagerImpl,但由于这是WebStart,您使用的JRE很可能来自Oracle而不是IBM JRE。

不确定从描述中是否清楚,但我已经知道了这一点——这是一个可怕的解决方案。应用程序开发人员不应该实现信任管理器之类的基本安全组件。我需要的是一种使用Java控制面板中现有的用户管理的信任存储的方法。如果用户决定信任CA证书,我的应用程序应该能够遵守该证书。为我的应用程序构建自定义信任管理器完全是错误的。