【发布时间】:2023-04-03 03:55:01
【问题描述】:
我正在尝试配置 Tomcat,以便我的 Web 应用程序可以使用 LDAPS。在 UAT 服务器上一切正常,但由于某种原因,生产服务器无法初始化信任库。
我已经打开调试(通过-Djavax.net.debug=all),错误是:
默认上下文初始化失败:java.io.IOException:密钥库被篡改,或密码不正确
我 100% 确定密码正确,因为我已经运行了 keytool 并列出了信任库的内容,并从工作的 UAT 服务器获取了相同的文件。
作为一个实验,我将 Tomcat 配置为对密钥库和信任库使用相同的存储文件(我意识到这不是典型的设置,但据我了解,文件格式等是相同的,因此它们都应该加载):
-Djavax.net.ssl.trustStorePassword=xxx
-Djavax.net.ssl.trustStore=C:\Program Files\Apache Software Foundation\Tomcat 7.0\bin\.keystore
-Djavax.net.ssl.keyStorePassword=xxx
-Djavax.net.ssl.keyStore=C:\Program Files\Apache Software Foundation\Tomcat 7.0\bin\.keystore
密钥库有效:
keyStore 是:C:\Program Files\Apache Software Foundation\Tomcat 7.0\bin.keystore
keyStore 类型是:jks
keyStore 提供者是:
初始化密钥库
SunX509 类型的初始化密钥管理器 ***
找到 : tomcat 的密钥
虽然信任库失败.. 对于相同的文件和密码!:
trustStore 是:C:\Program Files\Apache Software Foundation\Tomcat 7.0\bin.keystore
trustStore 类型是:jks
trustStore 提供者是:
初始化信任库
默认上下文初始化失败:java.io.IOException:密钥库被篡改,或密码不正确
从 Web 应用程序中,堆栈跟踪有更多详细信息(我不确定它是否有帮助。我研究了 TrustManagerFactoryImpl 的 java 源代码并将其与日志记录匹配,但它没有解释行为)
javax.naming.CommunicationException: <ldap url>:636 [Root exception is java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)]
at com.sun.jndi.ldap.Connection.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapClient.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapClient.getInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.InitialContext.<init>(Unknown Source)
at javax.naming.directory.InitialDirContext.<init>(Unknown Source)
at com.mycompany.fde.util.LDAPHelper.initialBindSSL(LDAPHelper.java:116)
at com.mycompany.fde.util.LDAPHelper.<init>(LDAPHelper.java:91)
at com.mycompany.fde.util.LDAPHelper.getInstance(LDAPHelper.java:58)
at com.mycompany.fde.server.work.StartupWork.startupStage1(StartupWork.java:224)
at com.mycompany.fde.server.work.StartupWork.call(StartupWork.java:121)
at com.mycompany.fde.server.work.StartupWork.call(StartupWork.java:47)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at javax.net.ssl.DefaultSSLSocketFactory.throwException(Unknown Source)
at javax.net.ssl.DefaultSSLSocketFactory.createSocket(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.jndi.ldap.Connection.createSocket(Unknown Source)
... 24 more
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at java.security.Provider$Service.newInstance(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at javax.net.ssl.SSLContext.getInstance(Unknown Source)
at javax.net.ssl.SSLContext.getDefault(Unknown Source)
at javax.net.ssl.SSLSocketFactory.getDefault(Unknown Source)
... 29 more
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at sun.security.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(Unknown Source)
at sun.security.ssl.SSLContextImpl$DefaultSSLContext.getDefaultTrustManager(Unknown Source)
at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
... 35 more
Caused by: java.security.UnrecoverableKeyException: Password verification failed
... 45 more
我完全不知所措 - 任何帮助/想法将不胜感激!
【问题讨论】:
-
从堆栈跟踪来看,
TrustManagerFactoryImpl.getCacertsKeyStore()期间似乎发生了一些事情。如果你在服务器上查看%JAVA_HOME%\jre\lib\security,你能看到那里有一个名为cacerts的文件吗? -
如果有
cacerts文件,可能它的密码不是默认密码,即“changeit”。 -
是的,我试过让它使用
cacerts(即使是在全新的Java安装之后)或jssecacerts,但它总是失败并出现同样的错误。这就是为什么我尝试使用自定义存储(与加载正常的密钥库相同)。 -
那么当您完全省略
-Djavax.net.ssl.trustStorePassword和-Djavax.net.ssl.trustStore参数时会发生什么?如果您需要 LDAP 的自定义证书,您还可以将证书导入 JVM 的默认信任库 (cacerts)。 -
不幸的是,同样的错误 - 调试表明它采用默认的
cacerts(或jssecacerts,如果我放一个)但失败