导入证书后仍然收到 SunCertPathBuilderException

Posted

技术标签:

【中文标题】导入证书后仍然收到 SunCertPathBuilderException【英文标题】:Still getting SunCertPathBuilderException after importing certificate 【发布时间】:2013-10-07 12:02:18 【问题描述】:

我正在尝试通过 ssl 连接到 ldap 服务器,我获得了服务器证书并安装如下:

keytool -keystore cacerts -importcert -alias ldapCert -file LdapCert.cer

我得到证书已成功安装消息,我可以使用以下命令验证证书是否已安装:

keytool -list -keystore cacerts

我可以在受信任的证书列表中找到我的证书。

这是我连接到 ldap 服务器的方式:

String host = "server.ip.here;
        String userDN = "CN=myuser,OU=EmployeesOU,OU=MainOU,dc=mydomain,dc=net";
        String userPassword = "mypassword";
        boolean ssl = true;

public static LdapContext connectToLdap(String host,
            String userDN, String userPassword,
            boolean ssl) throws Exception 

        System.out.println("connectToLdap");

        String hostPrefix = "ldap";
        String ldapPort = "389";
        if (ssl) 
            hostPrefix = "ldaps";
            ldapPort = "636";
        
        String providerUrl = hostPrefix + "://" + host + ":" + ldapPort;
        //System.out.println("####### LDAP URL: " + providerUrl);
        LdapContext ldapContext;
        Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, providerUrl);
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, userDN);
        ldapEnv.put(Context.SECURITY_CREDENTIALS, userPassword);
        ldapEnv.put("com.sun.jndi.ldap.read.timeout", 1000 * 10 + "");
        if (ssl) 
            ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        
        ldapEnv.put(Context.REFERRAL, "ignore");
        try 
            ldapContext = new InitialLdapContext(ldapEnv, null);
            System.out.println("success connection to ldap");
            return ldapContext;
         catch (Exception e) 
            System.out.println("failure connection to ldap");
            e.printStackTrace();
            return null;
        
    

从 cmd 安装证书并尝试运行应用程序后,我仍然遇到异常:

javax.naming.CommunicationException: simple bind failed: server.ip:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
        at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:197)
        at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2694)
        at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
        at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
        at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
        at javax.naming.InitialContext.init(InitialContext.java:223)
        at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:134)
        at ldap.LDAPUtils.connectToLdap(LDAPUtils.java:58)
        at Test.main(Test.java:43)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:192)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1074)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:128)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:744)
        at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
        at com.sun.jndi.ldap.Connection.run(Connection.java:808)
        at java.lang.Thread.run(Thread.java:619)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:325)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:219)
        at sun.security.validator.Validator.validate(Validator.java:218)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1053)
        ... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:320)

我尝试在连接到 ldap 之前使用 disableCertificateValidation 方法,如帖子Java client certificates over HTTPS/SSL

但它也给出了同样的例外。

请告知为什么我仍然收到此错误。

【问题讨论】:

【参考方案1】:

您不应修改 JDK 附带的 cacerts 文件。复制它并将证书添加到您自己的文件中,并通过系统属性javax.net.ssl.trustStore 告诉JSSE。

【讨论】:

【参考方案2】:

原因1:有两个冲突的JDK安装,删除其中一个并重新导入密钥,一切正常。

原因 2: 在某些测试机器上,我不得不从

复制生成的 cacerts 文件

java/jdk/jre/lib/security 转换为 java/jre/lib/security

原因 3: 如果您在 websphere 服务器上运行代码,则必须按照此处所述从 wensphere 配置密钥库和证书:

http://www-01.ibm.com/support/docview.wss?uid=swg21316850

【讨论】:

以上是关于导入证书后仍然收到 SunCertPathBuilderException的主要内容,如果未能解决你的问题,请参考以下文章

证书吊销后,我应该如何处理 fastlane match?

JAVA Tomcat SSL数字证书安装指南

恢复没有 p12 密码的签名证书?

JBoss 的 SSL 证书导入和配置

Apple Wallet - 替换证书并仍然将更新推送到旧卡

Wildfly 8.2:导入通配符证书,缺少中间证书