Spring Boot中SoapActionCallback如何配置密钥库与TLSv1
配置方案
SoapActionCallback仅负责设置SOAP请求的Action头,TLS协议、密钥库相关配置属于HTTP传输层逻辑,需要在WebServiceTemplate的消息发送器层面配置,不需要修改现有SOAP调用代码。
第一步:初始化SSL上下文
复用原有加载PKCS12密钥库、初始化TLSv1上下文的逻辑,封装为Spring托管的Bean即可,建议用try-with-resources处理文件流避免资源泄漏:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import java.io.InputStream; import java.security.KeyStore; import java.security.SecureRandom; @Configuration public class SoapClientConfig { private static final String KEYSTORE_PWD = "aaaa"; private static final String P12_PATH = "1234.p12"; private static final String TLS_VERSION = "TLSv1"; @Bean public SSLContext customSslContext() throws Exception { KeyStore keyStore = KeyStore.getInstance("PKCS12"); try (InputStream is = new ClassPathResource(P12_PATH).getInputStream()) { keyStore.load(is, KEYSTORE_PWD.toCharArray()); } KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keyStore, KEYSTORE_PWD.toCharArray()); SSLContext sslContext = SSLContext.getInstance(TLS_VERSION); sslContext.init(kmf.getKeyManagers(), null, new SecureRandom()); return sslContext; } }
第二步:配置自定义HTTP消息发送器
Spring WS默认使用Apache HttpComponents客户端发送HTTP请求,需要把上面生成的SSLContext注入到客户端中,强制使用TLSv1协议:
import org.apache.http.client.HttpClient; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClients; import org.springframework.ws.transport.http.HttpComponentsMessageSender; @Bean public HttpComponentsMessageSender soapMessageSender(SSLContext customSslContext) { // 指定仅支持TLSv1协议,和原有逻辑对齐 SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory( customSslContext, new String[]{TLS_VERSION}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier() ); HttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(socketFactory) .build(); return new HttpComponentsMessageSender(httpClient); }
如果测试环境存在域名不匹配的问题,可以临时把域名校验器替换为
NoopHostnameVerifier.INSTANCE,生产环境必须使用默认域名校验器避免中间人攻击风险。
第三步:将消息发送器绑定到WebServiceTemplate
配置WebServiceTemplate Bean时注入自定义的消息发送器,之后所有通过该实例发起的SOAP请求都会自动加载p12密钥库、使用TLSv1协议建立连接:
import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.ws.client.core.WebServiceTemplate; @Bean public WebServiceTemplate webServiceTemplate(Jaxb2Marshaller marshaller, HttpComponentsMessageSender soapMessageSender) { WebServiceTemplate template = new WebServiceTemplate(); template.setMarshaller(marshaller); template.setUnmarshaller(marshaller); template.setDefaultUri("https://test.com.asmx?WSDL"); template.setMessageSender(soapMessageSender); return template; }
调用逻辑保持不变
配置完成后,原有的调用代码不需要做任何修改即可正常工作:
ProvaResponse response = (ProvaResponse) getWebServiceTemplate().marshalSendAndReceive( request, new SoapActionCallback("http://www.test.com/Prova") );
提示:TLSv1属于已废弃的不安全协议,服务端支持的话优先升级到TLSv1.2及以上版本。如果服务端使用自签名证书,还需要在SSLContext初始化时添加自定义TrustManager加载信任证书。
内容的提问来源于stack exchange,提问作者Andrea Rovelli
相关产品推荐
相关产品推荐

