【问题标题】:Writing a Spring Boot WSDL *client* that presents a certificate for authentication编写提供认证证书的 Spring Boot WSDL *client*
【发布时间】:2015-10-23 15:10:07
【问题描述】:

我正在使用 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 用作客户端。在我的研究中,我看到一些页面暗示这可以通过一些注释来完成,但没有什么具体的。

我认为这一定是可能的,任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: ssl wsdl spring-boot spring-ws


    【解决方案1】:

    这是我所拥有的,使用 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 密钥库格式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 2020-10-15
      • 2014-11-25
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      相关资源
      最近更新 更多