Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将多个信任存储路径添加到“;java.net.ssl.trustStore”;?_Java_Ssl_Certificate - Fatal编程技术网

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

如何将多个信任存储路径添加到“;java.net.ssl.trustStore”;?,java,ssl,certificate,Java,Ssl,Certificate,我希望我的Java代码在一个密钥库中搜索服务器的CA证书。。。如果它找不到特定的证书(我认为只有当我尝试通过LDAP连接到目录服务器时才会知道),它应该在另一个密钥库中查找该证书,我知道该密钥库的路径 我试过这个: System.setProperty(“javax.net.ssl.trustStore”、System.getProperty(“java.home”)+“/lib/security/cacerts”+System.getProperty(“path.separator”)+pat

我希望我的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一样运行,如果没有,它就会失败

所以我的问题是:

  • 是否有方法将多文件密钥库路径添加到javax.net.ssl.trustStore

  • 如果不可能,我应该如何编写代码(我要求的是算法),这样它就不会在第一次搜索本身失败后抛出异常

  • 注:我对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
    ,它包装默认的信任管理器,捕获其异常,然后使用第二个存储初始化的另一个信任管理器重试。这是可行的,但是如果两个信任管理器都不接受您的证书,您需要确保它仍然抛出异常(否则,将存在安全漏洞)。如果您不熟悉JSSEAPI(或Java),那么它可能不是最好的选择

    此外,在代码中使用
    System.setProperty(“javax.net.ssl.trustStore”,…)
    时要小心:初始化默认的
    SSLContext
    ,需要初始化默认的
    SSLContext
    ,但是默认的
    SSLContext
    只初始化一次,这是第一次需要初始化。之后设置此系统属性将无效(当然,除非其他库中的其他类也依赖于此值)


    还不清楚您试图通过此实现什么,因为您总是能够成功地添加一个已经存在的安全提供商:

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

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

    虽然有点晚了,但我想对和提供的答案发表意见。事实上,这几乎是不可能的,因为有很多自定义代码,这是可能的。事实上,我们以前在一个类似问题的答案中看到过这一点:

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

    您的用例用于加载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();
        }
    
    }
    
    导入nl.altindag.sslcontext.SSLFactory;
    导入javax.net.ssl.SSLContext;
    导入java.security.cert.x509证书;
    导入java.util.List;
    公共类应用程序{
    公共静态void main(字符串[]args){
    字符串trustStorePath=。。。;
    char[]password=“password”.toCharArray();
    SSLFactory SSLFactory=SSLFactory.builder()
    .withDefaultTrustMaterial()
    .withTrustMaterial(信任存储路径、密码)
    .build();
    SSLContext SSLContext=sslFactory.getSslContext();
    List trustedCertificates=sslFactory.getTrustedCertificates();
    }
    }
    
    我很抱歉造成混淆:实际上“com.org.ldap.LDAPSocketFactory”是“com..ldap.LDAPSocketFactory”,我不想透露我公司的名称。我发布的代码并不完全是我的代码,我必须在插件代码中实现这一“增强”。这是一个合理的解决方案,但要注意它存在可维护性问题。您需要定期重新执行此过程-可能是在您获得新的JDK时,也可能是在您需要一些新的证书颁发机构证书时,等等。如果您这样做,在生产使用中,您应该自动执行此过程,否则它会咬到您的屁股。我们如何才能做到这一点?@BilalAhmedYaseen此答案正好说明: