使用WebServiceTemplate调用外部服务时遇SSLHandshake错误求助
解决WebServiceTemplate调用时的SSL证书SAN不匹配问题
老哥,这个问题我太熟了!从你贴的错误日志里能一眼看到核心问题:
java.security.cert.CertificateException: No subject alternative DNS name matching www.test-test.com found.
简单来说,你调用的www.test-test.com这个域名,不在目标服务SSL证书的**主题备用名称(Subject Alternative Name,SAN)**列表里——要么是证书里的域名和你实际调用的不一样(比如证书里是不带www的test-test.com),要么就是服务方的证书压根没把这个域名加进去。
下面分场景给你解决方案:
一、生产环境:规范解决(必选)
这是正经生产环境该用的方法,别搞歪门邪道:
- 先找服务方确认他们的SSL证书里有没有
www.test-test.com这个域名的SAN记录,如果没有,让他们更新证书; - 如果证书里的域名是不带
www的test-test.com,直接把你代码里的wsdlUrl改成https://test-test.com/xxx,保证调用域名和证书上的完全一致就行。
二、开发/测试环境:临时绕开(仅限测试!)
要是开发测试阶段不想被证书卡脖子,想快速跑通代码,可以临时跳过SSL证书校验,但生产绝对不能用!步骤如下:
- 先写个工具类,用来创建信任所有证书的SSL上下文:
import javax.net.ssl.*; import java.security.cert.X509Certificate; public class SslSkipUtils { public static SSLContext createTrustAllSslContext() throws Exception { // 自定义TrustManager,信任所有证书 X509TrustManager trustAllManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustAllManager}, new java.security.SecureRandom()); return sslContext; } }
- 修改你的WebServiceTemplate配置,把自定义的SSL连接工厂加上:
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(); Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath("wsdl"); webServiceTemplate.setDefaultUri(wsdlUrl); webServiceTemplate.setMarshaller(marshaller); webServiceTemplate.setUnmarshaller(marshaller); // 加入自定义SSL配置,跳过证书和主机名校验 try { SSLContext sslContext = SslSkipUtils.createTrustAllSslContext(); HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender(); messageSender.setSslContext(sslContext); // 同时忽略主机名匹配检查 messageSender.setHostnameVerifier((hostname, session) -> true); webServiceTemplate.setMessageSender(messageSender); } catch (Exception e) { e.printStackTrace(); } JAXBElement<MyClass> res = (JAXBElement<MyClass>) webServiceTemplate.marshalSendAndReceive(wsdlUrl, xClass);
⚠️ 再次提醒:这种方法等于完全放弃SSL的安全校验,本地测试用用就行,生产环境敢这么搞,等着被安全部门找上门!
三、额外排查点
- 检查下本地
hosts文件有没有把www.test-test.com映射到错误的IP,导致请求到了别的服务器,证书自然不匹配; - 如果目标服务用了CDN或者反向代理,得确认你调用的域名是不是CDN的域名,证书是不是CDN提供的,要是CDN证书里没这个域名也会出问题。
内容的提问来源于stack exchange,提问作者Ayoub EL ABOUSSI
相关产品推荐
相关产品推荐

