我正在Java 1.8上使用Spring Boot v 1.2.7.RELEASE编写服务器。我的代码完全由注释配置,除Maven pom外,目前没有XML。
我的Spring Boot服务器必须查询WSDL服务器以对用户进行身份验证。在这种情况下,我的服务器是WSDL服务的客户端。我的应用程序需要向WS服务器出示证书以对自身进行身份验证并获得访问权限,然后进行查询。因此,我有一个带有应用程序证书的JKS和一个服务器信任库JKS。
另外,到WS服务器的连接是通过https完成的,但是我认为这是由WebServiceGatewaySupport处理的。
我发现了许多WS客户端的示例,以及在Spring Boot中将SSL配置为服务器的许多示例,但是都没有显示如何将SSL用作客户端。在我的研究中,我看到一些页面暗示可以通过一些注释来完成此操作,但没有具体内容。
我认为这是有可能的,任何帮助将不胜感激,谢谢!
最佳答案
这是我使用Apache HttpClient 4.5.2所拥有的:
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLContext;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContexts;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.pox.dom.DomPoxMessageFactory;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
@Configuration
class ApplicationIntegrationTestConfiguration {
@Value("${lcm.request.endpoint}")
private String endpointUri;
@Value("${lcm.request.keystorepath}")
private Resource keyStore;
@Value("${lcm.request.keystorepass}")
private char[] keyStorePass;
@Value("${lcm.request.keystoretype}")
private String keyStoreType;
@Value("${lcm.request.truststorepath}")
private Resource trustStore;
@Value("${lcm.request.truststorepass}")
private char[] trustStorePass;
@Value("${lcm.request.truststoretype}")
private String trustStoreType;
private static final String ACCEPT_HEADER_VALUE = "application/xml";
@Bean
public WebServiceMessageSender messageSender(
LayeredConnectionSocketFactory factory) throws Exception {
Header header = new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_HEADER_VALUE);
List<Header> defaultHeaders = Arrays.asList(header);
CloseableHttpClient client = HttpClientBuilder.create()
.setSSLSocketFactory(factory)
.setDefaultHeaders(defaultHeaders)
.build();
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(
client);
// needed if used as a standalone client
//messageSender.afterPropertiesSet();
return messageSender;
}
@Bean
public LayeredConnectionSocketFactory sslFactory() {
try {
final KeyStore keystore = KeyStore.getInstance(this.keyStoreType);
try (InputStream readStream = this.keyStore.getInputStream()) {
keystore.load(readStream, this.keyStorePass);
}
final KeyStore truststore = KeyStore.getInstance(this.trustStoreType);
try (InputStream readStream = this.trustStore.getInputStream()) {
truststore.load(readStream, this.trustStorePass);
}
SSLContext sslContext = SSLContexts
.custom()
.loadTrustMaterial(truststore, null)
.loadKeyMaterial(keystore, this.keyStorePass)
.build();
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslContext,
new DefaultHostnameVerifier()
);
return sslConnectionFactory;
} catch (KeyManagementException | UnrecoverableKeyException |
NoSuchAlgorithmException | KeyStoreException
| CertificateException | IOException e) {
throw new IllegalArgumentException(String.format("Problem with keystore %s or truststore %s",
this.keyStore, this.trustStore), e);
}
}
@Bean
public PingClient pingClient(Jaxb2Marshaller marshaller,
WebServiceMessageFactory messageFactory, WebServiceMessageSender messageSender) {
PingClient client = new PingClient();
client.setDefaultUri(this.endpointUri + "/Ping/v1");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
client.setMessageFactory(messageFactory);
client.setMessageSender(messageSender);
return client;
}
// this bean is the key in selecting between SOAP and POX (plain old XML)
@Bean(name = MessageDispatcherServlet.DEFAULT_MESSAGE_FACTORY_BEAN_NAME)
public WebServiceMessageFactory messageFactory() {
return new DomPoxMessageFactory();
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("my.packages");
return marshaller;
}
}
我也有一个示例项目,其做的几乎与here相同,并且除了使用基本身份验证凭据here以外,其他都相同。他们没有适当的密钥库或信任库(因为很难获得密钥库或信任库的可发布版本),但是他们应该提供帮助。
请注意,您不能将.jks用作客户端证书,必须将其转换为.jceks密钥库格式。
关于ssl - 编写一个提供身份验证证书的Spring Boot WSDL * client *,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33305742/