首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何动态更新Truststore?

如何动态更新Truststore?
EN

Stack Overflow用户
提问于 2019-07-22 10:09:37
回答 4查看 7.9K关注 0票数 11

我目前已经在我的Spring应用程序中实现了相互TLS,并且我正在编程实现它,如下所示:

代码语言:javascript
复制
@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中,但这是行不通的。

代码语言:javascript
复制
@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端点时。

没有本地信任存储的客户证书身份验证我有一个证书列表,我只需要知道如何调用ReloadableX509TrustManageraddCertificates()方法。

EN

回答 4

Stack Overflow用户

发布于 2019-07-23 11:13:55

首先,使您的ReloadableX509TrustManager成为托管bean (如用@Component注释)。

代码语言:javascript
复制
@Component
class ReloadableX509TrustManager 
    implements X509TrustManager {
.....
    public ReloadableX509TrustManager(@Value("someValueFromAppConfig")String tspath){....}
.....

第二,在控制器中使用它,而不是创建新的控制器。

代码语言:javascript
复制
@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;
}

然后,跟随文章了解如何“重新加载”信任管理器。它可以通过更改大多数方法来实现,这些方法可以打包、保护并从某种服务器服务中调用它--或者将其公开并直接调用。是你的选择。

票数 3
EN

Stack Overflow用户

发布于 2019-07-24 13:11:46

更新2 : 我目前的解决方案是基于这些链接的,这些链接是针对Java的,但我不知道如何在Spring应用程序中实现它们。 https://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/

不管是不是春天,您的主要目标在广义上并不需要对应用程序技术的限制,重要的是您的应用程序(客户端)--它将是--能够在运行时期间的任意时刻将新的证书加载到客户端,并在运行时中进行更改。让我们这样说,我们可以在我们的类(TrustManager)中实现我们的逻辑,实现X509TrustManager

在客户端实现信任管理器

这里的目标是告诉运行时,您希望使用这个新类来验证证书。我们必须用我们的SSLContext实例化一个新的SSLSocketFactory,并使用它来指定一个新的SSLSocketFactory

代码语言:javascript
复制
try {
    String trustStorePath = "path to a truststore that you have";
    String trustStorePassword = "password of trustStore";
    String defaultTrustStore = "path to default truststore";

    // Initialize the new trustManager with the default trust store
    TrustManager trustManager = new TrustManager(defaultTrustStore);

    // Load the new Keystore and decrypt it
    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());

    // Add all of the certficates in the truststore and add them to the trust manager
    Enumeration<String> enumerator = ks.aliases();
    ArrayList<Certificate> certs = new ArrayList<>();
    while (enumerator.hasMoreElements()) {
        String currentAlias = enumerator.nextElement();
        certs.add(ks.getCertificate(currentAlias));
    }
    trustManager.addCertificates(certs);

    // Initialize the SSLContext and add it to the client conduit.
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, new TrustManager[] {trustManager}, null);

    // Set the new TrustManager in the client.
    HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(service).getConduit();
    TLSClientParameters tlsCP = new TLSClientParameters(); 
    httpConduit.setTlsClientParameters(tlsCP);
    tlsCP.setSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    e.printStackTrace();
}

如果你需要一个参考,这里,你会找到它。

票数 0
EN

Stack Overflow用户

发布于 2019-08-02 21:36:56

我还经历了同样的场景,在这个场景中,我必须动态更新我的spring的TrustManager。

  1. 我将证书上传到默认的SSLContext文件(即默认SSLContext SSLContext)--这将负责通过默认SSLContext建立的连接。
  2. 但是我还有两个不同的REST模板Beans,一个用于建立单向/互SSL连接,另一个用于2Way SSL连接。因为这些Beans是在启动时初始化的
    • 更改默认TrustManager不会更新REST模板的TrustManager。
    • 为此,我使用新的请求工厂动态更新了RestTemplate Bean,这解决了我的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57143673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档