java - 如何动态更新信任库?
问题描述
我目前已经在我的 Spring Boot 应用程序中实现了双向 TLS,并且我正在以编程方式进行,如下所示:
@Bean
public ServletWebServerFactory servContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
TomcatConnectorCustomizer tomcatConnectorCustomizer = new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(8443);
connector.setScheme("https");
connector.setSecure(true);
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setSSLEnabled(true);
protocol.setKeystoreType("PKCS12");
protocol.setKeystoreFile(keystorePath);
protocol.setKeystorePass(keystorePass);
//client must be authenticated (the cert he sends should be in our trust store)
protocol.setSSLVerifyClient(Boolean.toString(true));
protocol.setTruststoreFile(truststorePath);
protocol.setTruststorePass(truststorePass);
protocol.setKeyAlias("APP");
}
};
tomcat.addConnectorCustomizers(tomcatConnectorCustomizer);
return tomcat;
}
这工作正常且符合预期,但我有一个要求,我需要在运行时更新信任库(例如,当@getmapping
调用端点时)。
具体来说,我需要在不停止/重新启动应用程序的情况下将新证书添加到 TrustStore。所以我将不得不以某种方式修改我的应用程序的内存信任存储。
我怎样才能做到这一点?
我试图动态添加一个 bean,它将一个新的信任管理器添加到 SslContext,但这不起作用。
@GetMapping("/register")
public String Register() throws Exception {
ConfigurableApplicationContext configContext = (ConfigurableApplicationContext) appContext;
ConfigurableListableBeanFactory beanRegistry = configContext.getBeanFactory();
SSLContext sslContext = getSSLContext();
beanRegistry.registerSingleton("sslContext", sslContext);
return "okay";
}
public SSLContext getSSLContext() throws Exception {
TrustManager[] trustManagers = new TrustManager[] {
new ReloadableX509TrustManager(truststoreNewPath)
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);
return sslContext;
}
我还尝试将上述getSSLContext()
内容作为@bean 调用,但这也不起作用。
我当前的解决方案基于这些链接,它们适用于 Java,但我不确定如何在我的 Spring 应用程序中实现它们。
我找到了一个解决方案,它准确描述了如何拥有动态信任库,但我无法弄清楚如何在运行时重新加载信任库。例如,当调用 GET 端点时。
没有本地信任库的客户端证书身份验证
我有一个证书列表,我只需要知道如何调用ReloadableX509TrustManager
' addCertificates()
方法。
解决方案
首先,使您ReloadableX509TrustManager
的托管bean - 例如注释@Component
@Component
class ReloadableX509TrustManager
implements X509TrustManager {
.....
public ReloadableX509TrustManager(@Value("someValueFromAppConfig")String tspath){....}
.....
其次,在您的控制器中使用它而不是创建新的控制器,例如
@GetMapping("/register")
public String Register() throws Exception {
ConfigurableApplicationContext configContext = (ConfigurableApplicationContext) appContext;
ConfigurableListableBeanFactory beanRegistry = configContext.getBeanFactory();
SSLContext sslContext = getSSLContext();
beanRegistry.registerSingleton("sslContext", sslContext);
return "okay";
}
@Autowired private ReloadableX509TrustManager reloadableManager;
public SSLContext getSSLContext() throws Exception {
TrustManager[] trustManagers = new TrustManager[] {
reloadableManager
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);
return sslContext;
}
第三,按照文章了解如何“重新加载”该信任管理器。可以通过将大多数方法更改为 package protected 并从某种证书服务调用它来完成 - 或者将其公开并直接调用。这是你的选择。