我正在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/

10-11 22:29
查看更多