如何将多个信任库路径添加到“java.net.ssl.trustStore”?

2022-09-02 04:24:43

我希望我的Java代码在一个密钥库中搜索服务器的CA证书...如果它无法找到特定的证书(我认为只有当我尝试通过LDAP连接到目录服务器时才会知道),它应该在另一个密钥库中查找证书,我知道它的路径。

我试过这个:

System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts" + System.getProperty("path.separator") + path/to/second/keystore);

但它似乎没有奏效。

只添加一个路径(其中任何一个)有效,即如果找到证书,它就像charm一样运行,如果没有,则失败。

所以我的问题是:

  1. 有没有一种方法可以将多个密钥库路径添加到javax.net.ssl.trustStore?

  2. 如果不可能,我应该如何编写代码(我要求算法),以便它不会在第一次搜索后引发异常并失败?

附言:我对Java不是很熟悉。

以下是我的代码的相关部分:

if(useSSL)
{
  try 
  {   
    SSLContext se = SSLContext.getInstance("TLS");
    Security.addProvider(se.getProvider());
  }   
  catch(NoSuchAlgorithmException e) { }

  System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/lib/security/cacerts");

  com.org.ldap.LDAPSocketFactory ssf = new LDAPJSSESecureSocketFactory();
  LDAPConnection.setSocketFactory(ssf);
}

try 
{   
  lc = new LDAPConnection();
  lc.connect( ldapServer, ldapPort);
  lc.bind( ldapVersion,  ldapUser, (userInfo[1]).getBytes() );
}
catch (LDAPException le)
{
  le.printStackTrace();
}

答案 1

不能有多个 路径。javax.net.ssl.trustStore

最简单的方法是制作 JRE 的本地副本,并将证书从其他存储导入其中(有效地合并它们)。(请参阅。)cacertskeytool -importkeystore

否则,如果您事先知道所有 LDAP 连接都将使用第二个密钥库(并且您还希望能够对其他不相关的连接使用缺省信任库),那么您可以仅为该密钥库配置该信任库。我不熟悉 ,但它可能有一个选项可以这样做。(否则,您可以使用第二个信任库创建自定义初始化,并获取 ,如本答案中所述)。SSLSocketFactorycom.org.ldap.LDAPSocketFactorySSLContextSSLSocketFactory

另一种更复杂的方法是创建一个自定义,该自定义将包装默认信任管理器,捕获其异常,然后使用使用第二个存储初始化的另一个信任管理器再次尝试。这是可行的,但是如果信任管理器都不接受您的证书,您需要确保它仍然会抛出异常(否则,将存在安全漏洞)。如果您不熟悉JSSE API(或整个Java),它可能不是最佳选择。X509TrustManager

此外,在代码中使用时要小心:初始化默认值是读取的内容,但默认值仅初始化一次,这是第一次需要它。之后设置此系统属性将不起作用(当然,除非其他库中的其他类也依赖于此值)。System.setProperty("javax.net.ssl.trustStore", ...)SSLContextSSLContext


目前还不清楚你试图通过这个实现什么,因为你总是会成功地添加一个已经存在的安全提供商:

  try 
  {   
    SSLContext se = SSLContext.getInstance("TLS");
    Security.addProvider(se.getProvider());
  }   
  catch(NoSuchAlgorithmException e) { }

答案 2

不需要,只需将所有证书从一个信任库导入到另一个信任库,然后使用第二个信任库。