我有一个外部SOAP服务器,我必须通过https连接。我不想要的是使用keytool导入我从他们那里收到的两个.cer文件,因此我想以编程方式导入它们。
我收到的例外是sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我用于导入证书的代码
@Bean
public WSClient wsClient(Jaxb2Marshaller marshaller) throws Exception {
WSClient client = new WSClient();
client.setDefaultUri(getClientUrl());
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
createKeyStoreFromResource(ks, keyStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks, null);
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
ts.load(null);
createKeyStoreFromResource(ts, trustStore);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ts);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
messageSender.setKeyManagers(keyManagerFactory.getKeyManagers());
messageSender.setTrustManagers(trustManagerFactory.getTrustManagers());
messageSender.setSslSocketFactory(sslContext.getSocketFactory());
messageSender.setSslProtocol(sslContext.getProtocol());
messageSender.setSslProvider(sslContext.getProvider().getName());
messageSender.setHostnameVerifier((hostname, sslSession) -> true);
client.setMessageSender(messageSender);
return client;
}
private void createKeyStoreFromResource(KeyStore ks, Resource resource)
throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
BufferedInputStream bis = new BufferedInputStream(resource.getInputStream());
while(bis.available() > 0) {
Certificate certificate = cf.generateCertificate(bis);
ks.setCertificateEntry("fiddler" + bis.available(), certificate);
}
}
然后我public class WSClient extends WebServiceGatewaySupport
使用getWebServiceTemplate().marshalSendAndReceive()
keyStore
和trustStore
是两个Resource
个文件,位于类路径中,扩展名为.cer
keyStore
.cer文件具有以下格式
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
.
.
.
trustStore
.cer文件具有以下格式:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----