为了在开发环境中进行测试,我想忽略开发服务器的
https
证书问题。
我的 Web 服务客户端收到 :-
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
有许多类似的问题可以帮助我找到解决方案,但我想我会在这里为任何需要它的人发布这个特定问题的答案....
class UnTrustworthyTrustManager
implements X509TrustManager
{
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] arg0, String arg1)throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() { return null; }
}
然后
setDefaultUri("https://myServer/soapws/ws/");
Source requestSource = new ResourceSource(new ClassPathResource("MyRequest.xml"));
StringResult result = new StringResult();
WebServiceTemplate template = getWebServiceTemplate();
HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();
sender.setTrustManagers(new TrustManager[] { new UnTrustworthyTrustManager() });
template.setMessageSender(sender);
template.sendSourceAndReceiveToResult(requestSource, result);
System.out.println(result);
(需要 spring-ws-support)
如果您想将 SSL 配置为信任所有证书并直接在
SomeService
类中禁用主机名验证,而无需单独的 customizeClient
方法,则可以将设置直接集成到客户端使用中。以下是您如何在一个地方完成此操作:
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.http.HttpsUrlConnectionMessageSender;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
public class SomeService {
private final WebServiceTemplate webServiceTemplate;
public SomeService() throws Exception {
this.webServiceTemplate = new WebServiceTemplate();
// Step 1: Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Step 2: Initialize SSLContext with the trust manager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Step 3: Create a hostname verifier that allows all hosts
HostnameVerifier hostnameVerifier = (hostname, session) -> true;
// Step 4: Create a custom message sender
HttpsUrlConnectionMessageSender messageSender = new HttpsUrlConnectionMessageSender();
messageSender.setSslContext(sslContext);
messageSender.setHostnameVerifier(hostnameVerifier);
// Step 5: Set the message sender in WebServiceTemplate
this.webServiceTemplate.setMessageSender(messageSender);
}
// Use this WebServiceTemplate to make web service calls
public void someWebServiceCall() {
// Example of a web service call
// Object response = this.webServiceTemplate.marshalSendAndReceive("WebServiceUrl", requestPayload);
}
}
在上面的代码中:
WebServiceTemplate
在SomeService
的构造函数中初始化。someWebServiceCall
方法是一个占位符,您可以在其中使用 WebServiceTemplate
执行 Web 服务调用。此设置将为
WebServiceTemplate
内 SomeService
的所有使用应用不安全的 SSL 上下文和主机名验证器。一如既往,请记住安全风险,并将其仅用于开发目的。
如果您正在寻找一种更简单的方法来配置
WebServiceTemplate
以信任所有证书并禁用主机名验证,您可以通过扩展 WebServiceGatewaySupport
并直接配置 WebServiceTemplate
来实现。这种方法利用 Spring 的 CommonsHttpMessageSender
,使用更少的自定义代码。
将以下依赖项添加到
pom.xml
的 CommonsHttpMessageSender
:
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-support</artifactId>
<version>3.1.1</version> <!-- Check for the latest version -->
</dependency>
现在,在您的服务类中,您可以像这样配置
WebServiceTemplate
:
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.impl.client.HttpClients;
public class SomeService {
private final WebServiceTemplate webServiceTemplate;
public SomeService() throws Exception {
this.webServiceTemplate = new WebServiceTemplate();
// Set up HttpClient which trusts all certificates
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(builder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
// Use the HttpComponentsMessageSender which uses the HttpClient
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
messageSender.setHttpClient(httpClient);
// Set the message sender in the WebServiceTemplate
this.webServiceTemplate.setMessageSender(messageSender);
}
public void someWebServiceCall() {
// Your web service call logic goes here
}
}
在这个简化的代码中:
SSLContextBuilder
用于构建信任所有自签名证书的 SSL 上下文。HttpComponentsMessageSender
,它依赖于Apache HttpClient。NoopHostnameVerifier.INSTANCE
用于禁用主机名验证。此设置仍然存在安全隐患,只能用于测试或开发环境。对于生产环境,请始终确保正确的 SSL 证书管理和主机名验证。