在我们的java应用程序中,我们需要使用https协议与SSL上的服务器列表进行通信。要通信的服务器列表将在运行时更改。最初我们没有任何服务器的证书。在运行时,我们将获得新服务器的证书并将公钥证书添加到信任库中;与服务器的任何新的https连接都应该使用更新的信任库。
我们认为我们应该使用两个信任库,一个cacerts(默认一个jre附带)和其他包含我们在列表中动态添加/删除的服务器的证书。这将确保我们不修改java的默认TrustStore(cacerts)。
请建议如何实现这一目标。 此外,有没有办法只为java中的特定线程使用特定的信任存储,以便其他(现有的和新的)线程仍应使用默认的java trueststore(cacerts),并且一个特定的线程将使用特定的信任库服务器。
谢谢你, 迪帕克
答案 0 :(得分:5)
如果要动态导入证书,可能需要使用自定义x509TrustManager
。这在配置SSLContext
时完成,jSSLutils本身用于创建SSLSocketFactory
或SSLEngine
。
CertificateException
s是一个库,可让您包装现有的信任管理器并自定义某些设置。你不需要它,但它可能有所帮助。
这将遵循以下几点:
PKIXSSLContextFactory sslContextFactory = new PKIXSSLContextFactory();
sslContextFactory.setTrustManagerWrapper(new X509TrustManagerWrapper() {
@Override
public X509TrustManager wrapTrustManager(final X509TrustManager origManager) {
return new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return origManager.getAcceptedIssuers();
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
try {
// This will call the default trust manager
// which will throw an exception if it doesn't know the certificate
origManager.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
// If it throws an exception, check what this exception is
// the server certificate is in chain[0], you could
// implement a callback to the user to accept/refuse
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
origManager.checkClientTrusted(chain, authType);
}
};
}
});
SSLContext sslContext = sslContextFactory.buildSSLContext();
((PKIX)SSLContextFactory
和X509TrustManagerWrapper
来自jSSLutils,但其余部分可用于J2SE / J2EE。)
您可能想要捕获一些{{3}}(请参阅子类)。 如果您对用户进行回调,则SSL / TLS连接可能会因SSL / TLS握手超时而失败(如果回调需要很长时间才能回复。)
然后,您可以使用此SSLContext
作为默认值SSLContext.setSSLContext(...)
(来自Java 6),但这不一定是个好主意。如果可以,请将SSLContext
传递给建立SSL / TLS连接的库。如何做到这一点各不相同,但Apache HTTP Client 4.x有多个选项来配置其SSL设置,其中一个是传递KeyStore
,另一个是传递SSLContext
通过检查X509TrustManager
中的当前线程,您还可以使用每个线程而不是每个要连接的对象(依赖于库):这可能会使同步方面的事情变得更复杂一些线程管理/信任经理的“意识”。
答案 1 :(得分:2)
这个问题太老了,我怀疑我会帮助任何人,但这里有...
如果您想在不诉诸代码更改的情况下解决OP(原始海报)问题,您可以配置您的JVM(我只测试过Tomcat)以支持OP所需的配置: 1.单独留下'打包'的JDK cacerts文件 2.将您的证书导入一个单独的文件,让您的JAVA应用程序“信任”他们
我过去只是将我的附加证书导入一个单独的文件,然后在我的JVM启动中使用参数'-Djavax.net.ssl.trustStore = $ JAVA_HOME / jre / lib / security / jssecacerts'引用它,取得了巨大的成功但我想最近(有些)JAVA安全问题改变了随SDK一起分发的cacerts文件的自动包含。
所以我发现了一篇很棒的解决方案,使用了这篇文章中的英特尔和这些页面(稍作修改): - http://www.coderanch.com/t/529157/Tomcat/Configure-Tomcat-trust-store-cacerts - http://andyarismendi.blogspot.com/2012/01/changing-tomcats-ca-trust-keystore-file.html
我以前做的事情: - 将JVM trustStore参数设置为我的单独密钥库文件(我将其他证书导入),如下所示
我现在做什么: - 将trustStore参数设置为'packed'cacerts文件 - 将keyStore参数设置为我的“其他证书”文件 - 将keyStorePassword参数设置为我的keyStore密码(默认为changeit)
它看起来像什么:
-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts \
-Djavax.net.ssl.keyStore=$JAVA_HOME/jre/lib/security/jssecacerts \
-Djavax.net.ssl.keyStorePassword="changeit" \
希望这对某人有帮助。我不是100%你需要指定keyStore密码,因为你没有使用trustStore,但是当你这样做时它会起作用。