gpt4 book ai didi

java - 与服务连接时缺少客户端证书链问题

转载 作者:行者123 更新时间:2023-12-01 19:02:30 24 4
gpt4 key购买 nike

有一个与基于 SOAP 的服务连接的 Spring Boot 应用程序。我们的应用程序有一个 MQ 监听器,用于从本地队列接收消息。一旦消息从该队列中出列,它就会对服务进行 API 调用。

与基于 SOAP 的服务的所有通信都是通过 2 路 SSL 完成的。

现在我们在连接基于 SOAP 的服务时遇到了问题。基于 SOAP 的服务端间歇性收到缺少客户端证书链错误。

在我们的 JmsConfig 类中,我们将监听器工厂的并发性设置为 10,如下所示,以便并发执行和并行处理来自队列的消息。

 @Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(){
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
try {
factory.setConnectionFactory(cachingConnectionFactory(jmsConnectionFactoryX20()));
factory.setConcurrency("10");
} catch (JMSException e) {
e.printStackTrace();
}
return factory;
}

当我们在消息被使用后进一步从 Spring Boot 应用程序调用 SOAP 服务时,大多数消息的 SOAP 服务日志中都会出现缺少客户端证书链错误。在队列中批量加载 1k 条消息并随后并发执行时,大约 850 条消息在 SOAP 服务端失败,只有 150 条通过。

仅当以编程方式设置并发时才会出现错误,如上面的代码片段所示。如果我注释掉 setConcurrency 调用,所有 1k 消息都会在 SOAP 服务端得到处理,而不会出现任何证书链错误。

您能否看一下我们的配置并分享一些关于并发性导致此错误的原因的想法。

ApplicationWebServiceImpl.java(从 JMS 监听器方法调用 callWebService() 方法)

  import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapMessage;

@Service
public class ApplicationWebServiceImpl implements ApplicationWebServices {

@Autowired
private WebServiceTemplate wsTemplate;

@Value("${soap.clientEndpoint}")
private String clientEndpoint;

@Value("${soap.action}")
private String soapAction;

@Override
public Object callWebService(Object request, String serviceName) throws ClientApplicationException {

return wsTemplate.marshalSendAndReceive(clientEndpoint + serviceName, request, message -> {
SoapMessage msg = (SoapMessage) message;
msg.setSoapAction(soapAction + StringUtils.capitalize(serviceName));
});
}
}

ClientApplication(Spring启动主类)

@SpringBootApplication
@ComponentScan("com.abc.ca")
public class ClientApplication {

@Value(value = "${cert.keyStoreFileName}")
private String keyStoreFileName;

@Value(value = "${cert.trustStoreFileName}")
private String trustStoreFileName;

@Value(value = "${cert.disabledAlgorithms}")
private String disabledAlgorithms;

@PostConstruct
public void getKeyTrustStore() {
Security.setProperty("jdk.certpath.disabledAlgorithms", disabledAlgorithms);
String filePath = Thread.currentThread().getContextClassLoader().getResource(keyStoreFileName).getFile();

System.setProperty("javax.net.ssl.keyStore", filePath);
System.setProperty("javax.net.ssl.keyStorePassword", "changeme");
filePath = Thread.currentThread().getContextClassLoader().getResource(trustStoreFileName).getFile();

System.setProperty("javax.net.ssl.trustStore", filePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeme");
}

public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}

最佳答案

更新一下,我通过在 wsTemplate 上显式调用 setMessageSender 并设置 HttpsUrlConnectionMessageSender 解决了上述问题。

感谢@chughts 给我指点。

干杯!

 wsTemplate.setMessageSender(httpsUrlConnectionMessageSender());

@Bean
public HttpsUrlConnectionMessageSender httpsUrlConnectionMessageSender() throws Exception {
HttpsUrlConnectionMessageSender httpsUrlConnectionMessageSender = new
HttpsUrlConnectionMessageSender();

httpsUrlConnectionMessageSender.setTrustManagers(
loadDefaultTrustStore());

httpsUrlConnectionMessageSender.setKeyManagers(
loadKeyStore());

httpsUrlConnectionMessageSender.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
if ("localhost".equals(hostname)) {
return true;
}
return false;
}
});
return httpsUrlConnectionMessageSender;
}

private KeyManager[] loadKeyStore() throws KeyStoreException,
FileNotFoundException, IOException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException {

KeyStore keyStore = KeyStore.getInstance("jks");

FileInputStream fileInputStreamKeyStore = new FileInputStream("/ca/appKeystore.jks");
keyStore.load(fileInputStreamKeyStore,"changeme".toCharArray());

KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
keyFactory.init(keyStore,"changeme".toCharArray());
return keyFactory.getKeyManagers();
}

private TrustManager[] loadDefaultTrustStore() throws NoSuchAlgorithmException,
KeyStoreException {
TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
trustFactory.init((KeyStore)null);
return trustFactory.getTrustManagers();
}

关于java - 与服务连接时缺少客户端证书链问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59614064/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com