Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security

这里服务端开放了简单的SOAP的API,但是想获取数据时需要双向SSL以及WS-Security签名。

其中对应的xsd文件如下:



    
        
            
                
            
        
    

    
        
            
                
            
        
    

    
        
            
            
            
            
        
    

    
        
            
            
            
        
    

对应的Maven如下:



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.16.RELEASE
         
    
    com.example
    demo
    0.0.1-SNAPSHOT
    demo
    Demo project for Spring Boot

    
        1.8
    

    

        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            wsdl4j
            wsdl4j
            1.6.1
        

        
            org.springframework.ws
            spring-ws-core
            3.0.8.RELEASE
        

    

    
        

            
                org.springframework.boot
                spring-boot-maven-plugin
            

            
                org.codehaus.mojo
                jaxb2-maven-plugin
                2.5.0
                
                    
                        xjc
                        
                            xjc
                        
                    
                
                
                    
                        ${project.basedir}/src/main/resources/countries.xsd
                    
                
            

        
    

将源码跑起来(文章最后有源码的打包下载地址)

Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security_第1张图片

从中可以看到,HTTPS以及开启

这里使用SoapUI来测试,获取其wsdl

Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security_第2张图片

会提示如下错误

Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security_第3张图片

下面将证书挂上!

Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security_第4张图片

完成后测试下:

Java笔记-基于Spring Boot的SOAP双向SSL认证及WS-Security_第5张图片

可以看到连接成功,获取到了wsdl

 

客户端的配置

客户端中配置主要在SoapConfiguration.java中,首先是配置SSL双向认证:

private static final Resource KEYSTORE_LOCATION = new ClassPathResource("client.jks");
private static final String KEYSTORE_PASSWORD = "keystore";
...

@Bean
Jaxb2Marshaller marshaller() {
   Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
   marshaller.setContextPath("io.spring.guides.gs_producing_web_service");
   return marshaller;
}

@Bean
KeyStoreFactoryBean keyStore() {
   KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();
   factoryBean.setLocation(KEYSTORE_LOCATION);
   factoryBean.setPassword(KEYSTORE_PASSWORD);
   return factoryBean;
}

@Bean
TrustManagersFactoryBean trustManagers(KeyStoreFactoryBean keyStore) {
   TrustManagersFactoryBean factoryBean = new TrustManagersFactoryBean();
   factoryBean.setKeyStore(keyStore.getObject());
   return factoryBean;
}

@Bean
HttpsUrlConnectionMessageSender messageSender(
       KeyStoreFactoryBean keyStore,
       TrustManagersFactoryBean trustManagers
) throws Exception {
   HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();

   KeyManagersFactoryBean keyManagersFactoryBean = new KeyManagersFactoryBean();
   keyManagersFactoryBean.setKeyStore(keyStore.getObject());
   keyManagersFactoryBean.setPassword(KEYSTORE_PASSWORD);
   keyManagersFactoryBean.afterPropertiesSet();

   sender.setKeyManagers(keyManagersFactoryBean.getObject());

   sender.setTrustManagers(trustManagers.getObject());
   return sender;
}

双向SSL认证配置同样也需要在服务端进行设置。在高度安全的环境中客户端都需要有自己的证书,在与服务器通信之前都需要验证这些证书合不合法。

客户端的keystore存放的路径为:src/mian/resources/client.jks。这个jks中包含了客户端的私钥和公钥。使用spring-ws-security配置代替HttpsUrlConnectionMessageSender,使用这种方式可以实现SOAP的双向SSL认证。

下面是配置WS-Security:

@Bean
CryptoFactoryBean cryptoFactoryBean() throws IOException {
   CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
   cryptoFactoryBean.setKeyStoreLocation(KEYSTORE_LOCATION);
   cryptoFactoryBean.setKeyStorePassword(KEYSTORE_PASSWORD);
   return cryptoFactoryBean;
}

@Bean
Wss4jSecurityInterceptor securityInterceptor(CryptoFactoryBean cryptoFactoryBean) throws Exception {
   Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();

   securityInterceptor.setSecurementActions("Signature");
   securityInterceptor.setSecurementUsername(KEY_ALIAS);
   securityInterceptor.setSecurementPassword(KEYSTORE_PASSWORD);

   securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");
   securityInterceptor.setSecurementSignatureAlgorithm(WSS4JConstants.RSA_SHA1);
   securityInterceptor.setSecurementSignatureDigestAlgorithm(WSS4JConstants.SHA1);

   securityInterceptor.setSecurementSignatureCrypto(cryptoFactoryBean.getObject());

   return securityInterceptor;
}

这里需要为WSSJ4提供客户端的keystore及password。配置SecurityInterceptor,这个拦截器将每个SOAP消息都带上签名。

最后在GetCountryReponseClient中使用双向SSL及WS-Security:

@Bean
CountryClient countryClient(
       Jaxb2Marshaller marshaller,
       HttpsUrlConnectionMessageSender messageSender,
       Wss4jSecurityInterceptor securityInterceptor
) {
   CountryClient countryClient = new CountryClient();

   countryClient.setInterceptors(new ClientInterceptor[]{securityInterceptor});
   countryClient.setMessageSender(messageSender);

   countryClient.setMarshaller(marshaller);
   countryClient.setUnmarshaller(marshaller);

   return countryClient;
}

下面是测试下客户端,看看连接是否正常以及能否调用服务:

@SpringBootTest
public class CountryClientIntegrationTest {

   @Autowired
   CountryClient countryClient;

   @Test
   void shouldDownloadCountry() {
       // given
       String countryName = "Poland";

       // when
       Country country = countryClient.getCountry(countryName).getCountry();

       // then
       Country expectedCountry = new Country();
       expectedCountry.setName("Poland");
       expectedCountry.setCapital("Warsaw");
       expectedCountry.setCurrency(Currency.PLN);
       expectedCountry.setPopulation(38186860);

       assertThat(country.getName()).isEqualTo("Poland");
       assertThat(country.getCapital()).isEqualTo("Warsaw");
       assertThat(country.getCurrency()).isEqualTo(Currency.PLN);
       assertThat(country.getPopulation()).isEqualTo(38186860);
   }

}

服务端下载地址:

https://github.com/fengfanchen/Java/tree/master/SSLWebService

客户端下载地址:

https://github.com/fengfanchen/Java/tree/master/SSLWebServiceClient

 

 

 

 

你可能感兴趣的:(webservice,Java,Spring,Boot,spring,boot,https,ssl,java,webservice)