如何在SpringBoot中使用多个证书加载.keystore

时间:2018-07-03 15:58:01

标签: spring-boot ssl-certificate cxf keystore soap-client

我正在开发Spring Boot Application v2.0。从我的Spring Boot应用程序中,我正在发送SOAP请求以从Soap WS获取数据。我对多个Soap Web服务有多个Soap请求。每个Soap WS都有自己的证书。我使用Apache CXF v3.2.4自动生成“ ws client”类以及WS的所有其他内容。

证书采用PFX格式。我已经通过keytool成功创建了密钥库。我试图用此代码设置ssl.keyStore(同样,这不是设置这些值的好方法,我认为最好在application-properties中设置它……:

System.setProperty("javax.net.ssl.keyStore","path to my keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "mypassword");

我的密钥库中有3种不同的证书。它们都分别进行了测试,并且如果它们仅是密钥库中的一个,则它们都可以正常工作。问题是,例如,当我在密钥库中有3个证书时,仅加载列表中的第一个。

我在Internet上阅读了多篇文章,这篇文章最有趣,但不幸的是它没有解决我的问题(Registering multiple keystores in JVM)。

如果我按别名浏览证书链,则可以在控制台中看到所有证书。

 String storename = "C:/Certificates/mykeystore.ks";
            char[] storepass = "mypassword".toCharArray();
            String alias = "myalias";
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream(storename), storepass);             
            java.security.cert.Certificate[] cchain = ks.getCertificateChain(alias);            
            List mylist = new ArrayList();
        for (int i = 0; i < cchain.length; i++) {                 
            mylist.add(cchain[i]);
            }
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            CertPath cp = cf.generateCertPath(mylist);
            System.out.println(cp);

您有什么建议吗?!为了达到可以向一个密钥库加载多个证书或可以执行任何操作的阶段,我该怎么办? 预先感谢。

p.s。我也尝试通过Portecle将这些证书放在jdk / jre / lib / security / cacerts中,但没有效果。

1 个答案:

答案 0 :(得分:0)

对于每个Web服务,我认为您应该分别处理密钥库(和/或信任库),并在application.properties文件中进行配置。以下是使用特定证书集实例化Url Connection的SocketFactory的可行示例。

application.properties

keystore1.Path = src/main/resources/jks/yourKeyStoreFile1
keystore1.Password = keystore1pwd
truststore1.Path = src/main/resources/security1/cacerts
truststore1.Password = truststore1pwd

keystore2.Path = src/main/resources/jks/yourKeyStoreFile2
keystore2.Password = keystore2pwd
truststore2.Path = src/main/resources/security2/cacerts
truststore2.Password = truststore2pwd

当您使用其他WebService时,请使用其他SocketFactory。以下是.p12密钥库以及.jks信任库(证书)的示例。您可以轻松地将证书类型转换为其他格式。

@Component
public class MySocketFactory {

    @Value("${keystore1.Path}")
    String keystore1Path;

    @Value("${keystore1.Password}")
    String keystore1Password;

    @Value("${truststore1.Path}")
    String truststore1Path;

    @Value("${truststore1.Password}")
    String truststore1Password;

    public MySocketFactory() {

    }

    public SSLSocketFactory getSocketFactory() {

        try {

            SSLContext context = SSLContext.getInstance("TLS");

            KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            char[] keyStorePassword = keystore1Password.toCharArray();
            keyStore.load(new FileInputStream(keystore1Path), keyStorePassword);
            keyMgrFactory.init(keyStore, keyStorePassword);

            TrustManagerFactory trustStrFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyStore trustStore = KeyStore.getInstance("JKS");
            char[] trustStorePassword = truststore1Password.toCharArray();
            trustStore.load(new FileInputStream(truststore1Path), trustStorePassword);
            trustStrFactory.init(trustStore);

            context.init(keyMgrFactory.getKeyManagers(), trustStrFactory.getTrustManagers(), null);
            return context.getSocketFactory();

        } catch (Exception e) {
            System.err.println("Failed to create a server socket factory...");
            e.printStackTrace();
            return null;
        }
    }
}

为第二个SocketFactory创建相同的对象。希望这会有所帮助。