我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory
的现有应用程序以及启动服务器时加载的密钥库文件。
我有另一个应用程序,它创建了必须添加的证书
在服务器运行时动态地到密钥库文件。要执行此操作,
我在代码中创建了证书和私钥,然后编写它
到一个目录。该目录由检查新文件的bash脚本监视,如果出现,将导入现有的密钥库文件。
但是当尝试使用新导入的证书访问服务器时,握手失败。只有在重新启动服务器时,才能成功完成访问,我认为这意味着服务器不会重新加载添加的证书。
有没有办法用密钥库文件中的新条目更新正在运行的应用程序?
答案 0 :(得分:0)
将新证书导入密钥库不会刷新当前的SSLConext,因为没有告诉JVM密钥库已更改。
要做到这一点,你必须告诉你的应用程序一个新的证书被添加到你的密钥库中,而不是重新加载密钥库 - 尽管我知道它应该是不可能的 - 顺便说一句,可能的是您可以将新证书添加到当前的SSLContext See here。
要实现这一点,您需要提供一个知道新证书的bean - 可以是调用您的bash脚本的组件 - 您注入了SSLContext实例。
如果您使用微服务架构拆分应用程序,将一个模块委托给一个模块处理证书并重新加载它(使用适当的配置LB),因为密钥库已更新,这也很有趣。
答案 1 :(得分:0)
由于这似乎是一项不可能完成的任务,我决定采取一种解决方法。我在应用程序前面使用nginx作为代理。 Nginx能够使用多个CA根证书执行客户端身份验证,这正是我所需要的。应用程序和nginx之间的连接可以简单地通过HTTP完成,因为它们驻留在同一主机上(只是不同的端口)。
答案 2 :(得分:0)
丑陋的黑客警报
以下适用于我。我覆盖DefaultSSLContextFactory,存储每个创建的SSLContext并再次调用它的 init 方法。
要调用重新加载,我只需调用 UglyHackSSLContextFactory.reloadKeyStore()
package test;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import javax.net.ssl.SSLContext;
import org.restlet.engine.ssl.DefaultSslContextFactory;
public class UglyHackSSLContextFactory extends DefaultSslContextFactory {
private SSLContext _context = null;
public static ArrayList<UglyHackSSLContextFactory> instances = new ArrayList<UglyHackSSLContextFactory>();
// we need all used SSLContextFactories later, so store them
public UglyHackSSLContextFactory() {
instances.add(this);
}
// create a new context once and store it.
@Override
public SSLContext createSslContext() throws Exception {
if (this._context == null) {
this._context = super.createSslContext();
}
return this._context;
}
// re-init all _context instances
public static void reload() throws KeyManagementException, UnrecoverableKeyException,
KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException,
CertificateException, IOException {
for (final UglyHackSSLContextFactory f : instances) {
f.reinit();
}
}
// this is mostly copied from
// org.restlet.engine.ssl.DefaultSslContextFactory
private void reinit() throws KeyManagementException, KeyStoreException,
NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException,
UnrecoverableKeyException {
javax.net.ssl.KeyManagerFactory kmf = null;
if ((getKeyStorePath() != null) || (getKeyStoreProvider() != null)
|| (getKeyStoreType() != null)) {
// Loads the key store.
final KeyStore keyStore = (getKeyStoreProvider() != null) ? KeyStore.getInstance(
(getKeyStoreType() != null) ? getKeyStoreType() : KeyStore.getDefaultType(),
getKeyStoreProvider()) : KeyStore
.getInstance((getKeyStoreType() != null) ? getKeyStoreType() : KeyStore
.getDefaultType());
FileInputStream keyStoreInputStream = null;
try {
keyStoreInputStream = ((getKeyStorePath() != null) && (!"NONE"
.equals(getKeyStorePath()))) ? new FileInputStream(getKeyStorePath())
: null;
keyStore.load(keyStoreInputStream, getKeyStorePassword());
} finally {
if (keyStoreInputStream != null) {
keyStoreInputStream.close();
}
}
// Creates the key-manager factory.
kmf = javax.net.ssl.KeyManagerFactory.getInstance(getKeyManagerAlgorithm());
kmf.init(keyStore, getKeyStoreKeyPassword());
}
javax.net.ssl.TrustManagerFactory tmf = null;
if ((getTrustStorePath() != null) || (getTrustStoreProvider() != null)
|| (getTrustStoreType() != null)) {
// Loads the trust store.
final KeyStore trustStore = (getTrustStoreProvider() != null) ? KeyStore
.getInstance(
(getTrustStoreType() != null) ? getTrustStoreType() : KeyStore
.getDefaultType(), getTrustStoreProvider()) : KeyStore
.getInstance((getTrustStoreType() != null) ? getTrustStoreType() : KeyStore
.getDefaultType());
FileInputStream trustStoreInputStream = null;
try {
trustStoreInputStream = ((getTrustStorePath() != null) && (!"NONE"
.equals(getTrustStorePath()))) ? new FileInputStream(getTrustStorePath())
: null;
trustStore.load(trustStoreInputStream, getTrustStorePassword());
} finally {
if (trustStoreInputStream != null) {
trustStoreInputStream.close();
}
}
// Creates the trust-manager factory.
tmf = javax.net.ssl.TrustManagerFactory.getInstance(getTrustManagerAlgorithm());
tmf.init(trustStore);
}
SecureRandom sr = null;
if (getSecureRandomAlgorithm() != null) {
sr = SecureRandom.getInstance(getSecureRandomAlgorithm());
}
this._context.init(kmf != null ? kmf.getKeyManagers() : null,
tmf != null ? tmf.getTrustManagers() : null, sr);
}
}
希望这有帮助!