繁体   English   中英

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

[英]How to add multiple truststore paths to “java.net.ssl.trustStore”?

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

我试过这个:

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

但它似乎没有用。

只添加一个路径(其中之一)有效,即如果找到证书,它就会像魅力一样运行,否则就会失败。

所以我的问题是:

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

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

PS:我对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();
}

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

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

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

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

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


也不清楚你想用这个实现什么,因为你总是会成功添加一个已经存在的安全提供者:

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

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

虽然有点晚了,但我想对其他人提供的答案发表评论。 这几乎是不可能的,并且实际上有很多自定义代码是可能的,我们之前在一个类似问题的答案中已经看到了它:在 Java 中使用自定义信任库以及默认信任库

在多个项目遇到相同的挑战后,我认为创建一个库并将其公开以回馈社区会很方便。 请看这里: Github - SSLContext-Kickstart

您的用例的用途是加载 jdk 信任库和您自己的信任库:

import nl.altindag.sslcontext.SSLFactory;

import javax.net.ssl.SSLContext;
import java.security.cert.X509Certificate;
import java.util.List;

public class App {

    public static void main(String[] args) {
        String trustStorePath = ...;
        char[] password = "password".toCharArray();


        SSLFactory sslFactory = SSLFactory.builder()
                .withDefaultTrustMaterial()
                .withTrustMaterial(trustStorePath, password)
                .build();

        SSLContext sslContext = sslFactory.getSslContext();
        List<X509Certificate> trustedCertificates = sslFactory.getTrustedCertificates();
    }

}

暂无
暂无

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

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