【问题标题】:Dynamic SSL Keystore/Certificate selection动态 SSL 密钥库/证书选择
【发布时间】:2017-02-01 18:24:27
【问题描述】:

我的应用程序是在 websphere 上运行的 Web 服务提供者,而 SOAP Web 服务客户端由多个特定于每个客户端的密钥库组成。该应用程序需要迁移到 tomcat,我很震惊,因为我需要使用不同的证书来根据传入的客户端请求与后端服务器建立 TLS 连接

我正在使用 springboot 并且有一种配置 keystore 和 trustore 的方法。按照以下链接:

http://zoltanaltfatter.com/2016/04/30/soap-over-https-with-client-certificate-authentication/

我想在运行时根据客户端设置证书/密钥库。为此,我正在连接密钥库和配置(客户端)名称,以便我可以动态使用客户端特定的密钥库。但这是紧耦合的,每次我有一个新客户端时,我都需要为客户端创建一个条目并设置相应的密钥库。

但我想到了另一种方法,比如我将所有证书保存在一个密钥库中,我们如何动态访问客户端特定的证书?

【问题讨论】:

    标签: java ssl spring-boot certificate soap-client


    【解决方案1】:

    您可以使用密钥库来管理您的所有客户端证书,这些证书将由别名标识。

    默认KeyManager会在握手中选择第一个证书,所以在创建连接之前不需要建立自己的X509KeyManager来指定要使用的别名。见How I can tell alias of the wanted key-entry to SSLSocket before connecting?

    KeyStore keystore = ... //The keystore with all your certificates
    
    //The keymanager for an specific connection
    KeyManagerFactory kmf=  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keystore, password.toCharArray());
    
    //Create a keyManager wrapper that returns the alias to use
    final X509KeyManager origKm = (X509KeyManager)kmf.getKeyManagers()[0];
    X509KeyManager km = new X509KeyManager() {
       public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
           return "alias";
       }
    
       public X509Certificate[] getCertificateChain(String alias) {
           return origKm.getCertificateChain(alias);
       }
    
    // override the rest of the methods delegating to origKm ...
    }
    

    在HttpsUrlConnectionMessageSender 中注入新的keyManager

    HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
    //messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
    messageSender.setKeyManagers(new KeyManager[] { km });
    

    【讨论】:

    • 我尝试了你的方法,它奏效了,但我遇到了另一个问题。我声明了 X509Keymanager 并覆盖了上述两种方法,但是当我调用目标服务器时,我收到以下错误消息main, RECV TLSv1.2 ALERT: fatal, unexpected_message main, handling exception: javax.net.ssl.SSLException: Received fatal 我通过将 KeyManager 对象提供给 HttpsUrlConnectionMessageSender 而不是 X509KeyManager 来修复此错误。服务器 SSL 跟踪显示服务器没有从客户端获取 CERTIFICATE-VERIFY 消息,因此连接突然终止。
    • 确切的错误是:Caused by: org.springframework.ws.client.WebServiceIOException: I/O error: Received fatal alert: unexpected_message; nested exception is javax.net.ssl.SSLException: Received fatal alert: unexpected_message at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:561) ~[spring-ws-core- 2.3.1.RELEASE.jar:2.3.1.RELEASE] .....Caused by: javax.net.ssl.SSLException: Received fatal alert: unexpected_message at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.8.0_71]
    • 我解决了这个问题,看起来我的应用程序将私钥获取为空,因为我没有覆盖该方法。这是修复:@Override public PrivateKey getPrivateKey(String arg0) { // TODO Auto-generated method stub return origKm.getPrivateKey(arg0); }
    • 您能否编辑答案以添加您的第一条评论的修复? mi 不清楚要改变什么。还可以考虑将答案标记为已接受
    猜你喜欢
    • 2011-08-17
    • 2013-01-02
    • 2017-05-10
    • 2014-05-06
    • 2018-08-18
    • 2012-03-08
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多