Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

栏目: IT技术 · 发布时间: 4年前

内容简介:When creating applications for industries with high demand for security we often need to apply uncommon security measures. For machine-to-machine communicationRecently at 98elements we integrated a SOAP interface of a bank to automate a process that includ

When creating applications for industries with high demand for security we often need to apply uncommon security measures. For machine-to-machine communication SOAP is still used beside REST -style APIs especially in systems from the early 2000s.

Recently at 98elements we integrated a SOAP interface of a bank to automate a process that includes handling incoming money transfers and sending outgoing transfers to the clients. The set of security technologies for SOAP APIs is different from what we use on daily basis. If we want to integrate such an API in our application we need to configure security properly. However, sometimes it’s hard to do it with the existing documentation. Let’s see how to configure the most common security measures for SOAP protocol - Two-Way SSL and WS-Security in a Spring Boot client!

Running the Server

Let’s take a look at the sample code at GitHub . This repository contains two directories: server and client . The server exposes a simple SOAP API for retrieving data about countries secured by Two-Way SSL and WS-Security signature. The API is based on Spring Guides - Consuming Web Service .

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring.io/guides/gs-producing-web-service"
           targetNamespace="http://spring.io/guides/gs-producing-web-service" elementFormDefault="qualified">

    <xs:element name="getCountryRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="population" type="xs:int"/>
            <xs:element name="capital" type="xs:string"/>
            <xs:element name="currency" type="tns:currency"/>
        </xs:sequence>
    </xs:complexType>

    <xs:simpleType name="currency">
        <xs:restriction base="xs:string">
            <xs:enumeration value="GBP"/>
            <xs:enumeration value="EUR"/>
            <xs:enumeration value="PLN"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

You can start the server using Gradle:

$ cd server
$ ./gradlew bootRun

Security Check

Let’s pause here for a second. Instead of jumping to the client code, let’s first try to connect to the server using SoapUI to make sure it actually works as described above! We’ll start with creating a new project:

Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

It turns out that we are missing Two-Way SSL configuration. Without it we won’t even be able to download the WSDL:

Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

Let’s configure Two-Way SSL in PreferencesSSL Settings and check again. The client’s keystore is located in client/src/main/resources/client-keystore.jks .  The keystore password is “keystore”.

Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

Now we are able to download the WSDL and create a SoapUI project. Let’s try to make a request:

Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

We are still missing WS-Security configuration as indicated by the error message:

Configuring a SOAP Client with Two-Way SSL and WS-Security using Spring Boot

Now that we’re certain that the server is configured to allow only secure clients let’s see how to connect to it from Java code!

Client's Configuration

The client’s configuration is located in SoapConfiguration.java . The first part of the configuration sets up Two-Way SSL.

private static final Resource KEYSTORE_LOCATION = new ClassPathResource("client-keystore.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;
}

Two-Way SSL adds authentication of the client by the server to the standard SSL protocol. In highly secure environments every client has its own certificate and must be authenticated by the server before the communication starts.

The client’s keystore located in src/main/resources/client-keystore.jks contains client’s private and public keys (so the client can present itself to the server) and the server’s certificate (so the client can verify the server’s identity). We use spring-ws-security to configure an instance of HttpsUrlConnectionMessageSender so it can send SOAP messages using Two-Way SSL.

The next part of the configuration sets up 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;
}

We have to provide keystore’s location and password to another library - WSSJ4 - which implements WS-Security for Java. Then, we configure a SecurityInterceptor that signs every outgoing message with client’s private key.

Finally, we can set up our GetCountryResponseClient with Two-Way SSL and 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;
}

Testing the Client

Let’s run a test that will ensure that the client connection works. Remember to start the server before executing the test.

@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);
   }

}
$ cd client
$ ./gradlew test
BUILD SUCCESSFUL in 6s

We have successfully connected to a SOAP server using Two-Way SSL and WS-Security!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP+MySQL八大动态Web应用实战

PHP+MySQL八大动态Web应用实战

Jono Bacom / 吴连河、李剑 / 电子工业出版社 / 2008-6 / 68.00元

本书详细介绍了利用PHP+MySQL开发常见类型Web应用程序的完整设计和编码技术,并对整体设计与关键代码给予了细致、深入的剖析。其内容注重实践,提供了翔实完整的实战代码;思路独树一帜,突破过多描述语言细节的窠臼;行文风趣幽默,轻松调侃中将项目的完整设计过程分析得一清二楚。书中的示例项目完整而实用,读者甚至无需任何改动即可在实际中加以运用。. 本书适合对PHP/MySQL有初步了解但缺乏完整......一起来看看 《PHP+MySQL八大动态Web应用实战》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具