Chapter 7. Securing your Web services with Spring-WS

7.1. Introduction

This chapter explains how to add WS-Security aspects to your Web services. We will focus on the three different areas of WS-Security, namely:

Authentication.  This is the process of determining whether a principal is who they claim to be. In this context, a "principal" generally means a user, device or some other system which can perform an action in your application.

Digital signatures.  The digital signature of a message is a piece of information based on both the document and the signer's private key. It is created through the use of a hash function and a private signing function (encrypting with the signer's private key).

Encryption and Decryption.  Encryption is the process of transforming data into a form that is impossible to read without the appropriate key. It is mainly used to keep information hidden from anyone for whom it is not intended. Decryption is the reverse of encryption; it is the process of transforming of encrypted data back into an readable form.

All of these three areas are implemented using the XwsSecurityInterceptor, which we will describe in Section 7.2, “XwsSecurityInterceptor.

Note

Note that WS-Security (especially encryption and signing) requires substantial amounts of memory, and will also decrease performance. If performance is important to you, you might want to consider not using WS-Security.

7.2. XwsSecurityInterceptor

The XwsSecurityInterceptor is an EndpointInterceptor (see Section 5.4.4, “Intercepting requests - the EndpointInterceptor interface”) that is based on SUN's XML and Web Services Security package (XWSS). This WS-Security implementation is part of the Java Web Services Developer Pack (Java WSDP).

Like any other endpoint interceptor, it is defined in the endpoint mapping (see Section 5.4, “Endpoint mappings” ). This means that you can be selective about adding WS-Security support: some endpoint mappings require it, while others do not.

The XwsSecurityInterceptor requires a security policy file to operate. This XML file tells the interceptor what security aspects to require from incoming SOAP messages, and what aspects to add to outgoing messages. The basic format of the policy file will be explained in the following sections, but you can find a more in-depth tutorial here. You can set the policy with the policyConfiguration property, which requires a Spring resource. The policy file can contain multiple elements, e.g. require a username token on incoming messages, and sign all outgoing messages. It contains a SecurityConfiguration element as root (not a JAXRPCSecurity element).

Additionally, the security interceptor requires one or more CallbackHandlers to operate. These handlers are used to retrieve certificates, private keys, validate user credentials, etc. Spring-WS offers handlers for most common security concerns, e.g. authenticating against a Acegi authentication manager, signing outgoing messages based on a X509 certificate. The following sections will indicate what callback handler to use for which security concern. You can set the callback handlers using the callbackHandler or callbackHandlers property.

Here is an example that shows how to wire the XwsSecurityInterceptor up:

<beans>
    <bean id="wsSecurityInterceptor"
        class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
        <property name="policyConfiguration" value="classpath:securityPolicy.xml"/>
        <property name="callbackHandlers">
            <list>
                <ref bean="certificateHandler"/>
                <ref bean="authenticationHandler"/>
            </list>
        </property>
    </bean>
    ...
</beans>

This interceptor is configured using the securityPolicy.xml file on the classpath. It uses two callback handlers which are defined further on in the file.

7.3. Keystores

For most cryptographic operations, you will use standard java.security.KeyStore objects. This includes certificate verification, message signing, signature verification, and encryption, but excludes username and time-stamp verification. This section aims to give you some background knowledge on keystores, and the Java tools that you can use to store keys and certificates in a keystore file. This information is mostly not related to Spring-WS, but to the general cryptographic features of Java.

The java.security.KeyStore class represents a storage facility for cryptographic keys and certificates. It can contain three different sort of elements:

Private Keys.  These keys are used for self-authentication. The private key is accompanied by certificate chain for the corresponding public key. Within the field of WS-Security, this accounts to message signing and message decryption.

Symmetric Keys.  Symmetric (or secret) keys are used for message encryption and decryption as well. The difference being that both sides (sender and recipient) share the same, secret key.

Trusted certificates.  These X509 certificates are called a trusted certificate because the keystore owner trusts that the public key in the certificates indeed belong to the owner of the certificate. Within WS-Security, these certificates are used for certificate validation, signature verification, and encryption.

7.3.1. KeyTool

Supplied with your Java Virtual Machine is the keytool program, a key and certificate management utility. You can use this tool to create new keystores, add new private keys and certificates to them, etc. It is beyond the scope of this document to provide a full reference of the keytool command, but you can find a reference here, or by giving the command keytool -help on the command line.

7.3.2. KeyStoreFactoryBean

To easily load a keystore using Spring configuration, you can use the KeyStoreFactoryBean. It has a resource location property, which you can set to point to the path of the keystore to load. A password may be given to check the integrity of the keystore data. If a password is not given, integrity checking is not performed.

<bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
    <property name="password" value="password"/>
    <property name="location" value="classpath:org/springframework/ws/soap/security/xwss/test-keystore.jks"/>
</bean>

Caution

If you don't specify the location property, a new, empty keystore will be created, which is most likely not what you want.

7.3.3. KeyStoreCallbackHandler

To use the keystores within a XwsSecurityInterceptor, you will need to define a KeyStoreCallbackHandler. This callback has three properties with type keystore: (keyStore, trustStore, and symmetricStore). The exact stores used by the handler depend on the cryptographic operations that are to be performed by this handler. For private key operation, the keyStore is used, for symmetric key operations the symmetricStore, and for determining trust relationships, the trustStore. The following table indicates this:

Cryptographic operationKeystore used
Certificate validation first the keyStore, then the trustStore
Decryption based on private keykeyStore
Decryption based on symmetric keysymmetricStore
Encryption based on public key certificatetrustStore
Encryption based on symmetric keysymmetricStore
SigningkeyStore
Signature verificationtrustStore

Additionally, the KeyStoreCallbackHandler has a privateKeyPassword property, which should be set to unlock the private key(s) contained in the keyStore.

If the symmetricStore is not set, it will default to the keyStore. If the key or trust store is not set, the callback handler will use the standard Java mechanism to load or create it. Refer to the JavaDoc of the KeyStoreCallbackHandler to know how this mechanism works.

For instance, if you want to use the KeyStoreCallbackHandler to validate incoming certificates or signatures, you would use a trust store, like so:

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="trustStore" ref="trustStore"/>
    </bean>

    <bean id="trustStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:truststore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

If you want to use it to decrypt incoming certificates or sign outgoing messages, you would use a key store, like so:

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="keyStore" ref="keyStore"/>
        <property name="privateKeyPassword" value="changeit"/>
    </bean>

    <bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:keystore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

The following sections will indicate where the KeyStoreCallbackHandler can be used, and which properties to set for particular cryptographic operations.

7.4. Authentication

As stated in the introduction, authentication is the task of determining whether a principal is who they claim to be. Within WS-Security, authentication can take two forms: using a username and password token (using either a plain text password or a password digest), or using a X509 certificate.

7.4.1. Plain Text Username Authentication

The simplest form of username authentication uses plain text passwords. In this scenario, the SOAP message will contain a UsernameToken element, which itself contains a Username element and a Password element which contains the plain text password. Plain text authentication can be compared to the Basic Authentication provided by HTTP servers.

Warning

Note that plain text passwords are not very secure. Therefore, you should always add additional security measures to your transport layer if you are using them (using HTTPS instead of plain HTTP, for instance).

To require that every incoming message contains a UsernameToken with a plain text password, the security policy file should contain a RequireUsernameToken element, with the passwordDigestRequired attribute set to false. You can find a reference of possible child elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    ...
    <xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/>
    ...
</xwss:SecurityConfiguration>

If the username token is not present, the XwsSecurityInterceptor will return a SOAP Fault to the sender. If it is present, it will fire a PasswordValidationCallback with a PlainTextPasswordRequest to the registered handlers. Within Spring-WS, there are three classes which handle this particular callback.

7.4.1.1. SimplePasswordValidationCallbackHandler

The simplest password validation handler is the SimplePasswordValidationCallbackHandler. This handler validates passwords against an in-memory Properties object, which you can specify using the users property, like so:

<bean id="passwordValidationHandler"
    class="org.springframework.ws.soap.security.xwss.callback.SimplePasswordValidationCallbackHandler">
    <property name="users">
        <props>
            <prop key="Bert">Ernie</prop>
        </props>
    </property>
</bean>

In this case, we are only allowing the user "Bert" to log in using the password "Ernie".

7.4.1.2. AcegiPlainTextPasswordValidationCallbackHandler

The AcegiPlainTextPasswordValidationCallbackHandler uses the excellent Acegi Security Framework to authenticate users. It is beyond the scope of this document to describe Acegi, but suffice it to say that Acegi is a full-fledged security framework. You can read more about Acegi in the Acegi reference documentation.

The AcegiPlainTextPasswordValidationCallbackHandler requires an Acegi AuthenticationManager to operate. It uses this manager to authenticate against a UsernamePasswordAuthenticationToken that it creates. If authentication is successful, the token is stored in the SecurityContextHolder. You can set the authentication manager using the authenticationManager property:

<beans>
  <bean id="acegiHandler"
      class="org.springframework.ws.soap.security.xwss.callback.acegi.AcegiPlainTextPasswordValidationCallbackHandler">
    <property name="authenticationManager" ref="authenticationManager"/>
  </bean>

  <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
          <bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
              <property name="userDetailsService" ref="userDetailsService"/>
          </bean>
      </property>
  </bean>

  <bean id="userDetailsService" class="com.mycompany.app.dao.UserDetailService" />
  ...
</beans>

7.4.1.3. JaasPlainTextPasswordValidationCallbackHandler

The JaasPlainTextPasswordValidationCallbackHandler is based on the standard Java Authentication and Authorization Service. It is beyond the scope of this document to provide a full introduction into JAAS, but there is a good tutorial available.

The JaasPlainTextPasswordValidationCallbackHandler requires only a loginContextName to operate. It creates a new JAAS LoginContext using this name, and handles the standard JAAS NameCallback and PasswordCallback using the username and password provided in the SOAP message. This means that this callback handler integrates with any JAAS LoginModule that fires these callbacks during the login() phase, which is standard behavior.

You can wire up a JaasPlainTextPasswordValidationCallbackHandler as follows:

<bean id="jaasValidationHandler"
    class="org.springframework.ws.soap.security.xwss.callback.jaas.JaasPlainTextPasswordValidationCallbackHandler">
    <property name="loginContextName" value="MyLoginModule" />
</bean>

In this case, the callback handler uses the LoginContext named "MyLoginModule". This module should be defined in your jaas.config file, as explained in the abovementioned tutorial.

7.4.2. Digest Username Authentication

When using password digests, the SOAP message also contains a UsernameToken element, which itself contains a Username element and a Password element. The difference is that the password is not sent as plain text, but as a digest. The recipient compares this digest to the digest he calculated from the known password of the user, and if they are the same, the user is authenticated. It can be compared to the Digest Authentication provided by HTTP servers.

To require that every incoming message contains a UsernameToken element with a password digest, the security policy file should contain a RequireUsernameToken element, with the passwordDigestRequired attribute set to true. Additionally, the nonceRequired should be set to true: You can find a reference of possible child elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    ...
    <xwss:RequireUsernameToken passwordDigestRequired="true" nonceRequired="true"/>
    ...
</xwss:SecurityConfiguration>

If the username token is not present, the XwsSecurityInterceptor will return a SOAP Fault to the sender. If it is present, it will fire a PasswordValidationCallback with a DigestPasswordRequest to the registered handlers. Within Spring-WS, there are two classes which handle this particular callback.

7.4.2.1. SimplePasswordValidationCallbackHandler

The SimplePasswordValidationCallbackHandler can handle both plain text passwords as well as password digests. It is described in Section 7.4.1.1, “SimplePasswordValidationCallbackHandler”.

7.4.2.2. AcegiDigestPasswordValidationCallbackHandler

The AcegiPlainTextPasswordValidationCallbackHandler requires an Acegi UserDetailService to operate. It uses this service to retrieve the password of the user specified in the token. The digest of the password contained in this details object is then compared with the digest in the message. If they are equal, the user has successfully authenticated, and a UsernamePasswordAuthenticationToken is stored in the SecurityContextHolder. You can set the service using the userDetailsService. Additionally, you can set a userCache property, to cache loaded user details.

<beans>
    <bean class="org.springframework.ws.soap.security.xwss.callback.acegi.AcegiDigestPasswordValidationCallbackHandler">
        <property name="userDetailsService" ref="userDetailsService"/>
    </bean>

    <bean id="userDetailsService" class="com.mycompany.app.dao.UserDetailService" />
    ...
</beans>

7.4.3. Certificate Authentication

A more secure way of authentication uses X509 certificates. In this scenerario, the SOAP message contains a BinarySecurityToken, which contains a Base 64-encoded version of a X509 certificate. The recipient is used by the recipient to authenticate. The certificate stored in the message is also used to sign the message (see Section 7.5.1, “Verifying Signatures”).

To make sure that all incoming SOAP messages carry a BinarySecurityToken, the security policy file should contain a RequireSignature element. This element can further carry other elements, which will be covered in Section 7.5.1, “Verifying Signatures”. You can find a reference of possible child elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    ...
    <xwss:RequireSignature requireTimestamp="false">
    ...
</xwss:SecurityConfiguration>

When a message arrives that carries no certificate, the XwsSecurityInterceptor will return a SOAP Fault to the sender. If it is present, it will fire a CertificateValidationCallback. There are three handlers within Spring-WS which handle this callback for authentication purposes.

Note

In most cases, certificate authentication should be preceded by certificate validation, since you only want to authenticate against valid certificates. Invalid certificates such as certificates for which the expiration date has passed, or which are not in your store of trusted certificates, should be ignored.

In Spring-WS terms, this means that the AcegiCertificateValidationCallbackHandler or JaasCertificateValidationCallbackHandler should be preceded by KeyStoreCallbackHandler. This can be accomplished by setting the order of the callbackHandlers property in the configuration of the XwsSecurityInterceptor:

<bean id="wsSecurityInterceptor"
    class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
    <property name="policyConfiguration" value="classpath:securityPolicy.xml"/>
    <property name="callbackHandlers">
        <list>
            <ref bean="keyStoreHandler"/>
            <ref bean="acegiHandler"/>
        </list>
    </property>
</bean>

Using this setup, the interceptor will first determine if the certificate in the message is valid using the keystore, and then authenticate against it.

7.4.3.1. KeyStoreCallbackHandler

The KeyStoreCallbackHandler uses a standard Java keystore to validate certificates. This certificate validation process consists of the following steps:

  1. First, the handler will check whether the certificate is in the private keyStore. If it is, it is valid.

  2. If the certificate is not in the private keystore, the handler will check whether the the current date and time are within the validity period given in the certificate. If they are not, the certificate is invalid; if it is, it will continue with the final step.

  3. Finally, a certification path for the certificate is created. This basically means that the handler will determine whether the certificate has been issued by any of the certificate authorities in the trustStore. If a certification path can be built successfully, the certificate is valid. Otherwise, the certificate is not.

To use the KeyStoreCallbackHandler for certificate validation purposes, you will most likely set only the trustStore property:

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="trustStore" ref="trustStore"/>
    </bean>

    <bean id="trustStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:truststore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

Using this setup, the certificate that is to be validated must either be in the trust store itself, or the trust store must contain a certificate authority that issued the certificate.

7.4.3.2. AcegiCertificateValidationCallbackHandler

The AcegiCertificateValidationCallbackHandler requires an Acegi AuthenticationManager to operate. It uses this manager to authenticate against a X509AuthenticationToken that it creates. The configured authentication manager is expected to supply a provider which can handle this token (usually an instance of X509AuthenticationProvider). If authentication is succesful, the token is stored in the SecurityContextHolder. You can set the authentication manager using the authenticationManager property:

<beans>
    <bean id="acegiCertificateHandler"
        class="org.springframework.ws.soap.security.xwss.callback.acegi.AcegiCertificateValidationCallbackHandler">
        <property name="authenticationManager" ref="authenticationManager"/>
    </bean>

    <bean id="authenticationManager"
        class="org.acegisecurity.providers.ProviderManager">
        <property name="providers">
            <bean class="org.acegisecurity.providers.x509.X509AuthenticationProvider">
                <property name="x509AuthoritiesPopulator">
                    <bean class="org.acegisecurity.providers.x509.populator.DaoX509AuthoritiesPopulator">
                        <property name="userDetailsService" ref="userDetailsService"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

  <bean id="userDetailsService" class="com.mycompany.app.dao.UserDetailService" />
  ...
</beans>

In this case, we are using a custom user details service to obtain authentication details based on the certificate. Refer to the Acegi reference documentation for more information about authentication against X509 certificates.

7.4.3.3. JaasCertificateValidationCallbackHandler

The JaasCertificateValidationCallbackHandler requires a loginContextName to operate. It creates a new JAAS LoginContext using this name and with the X500Principal of the certificate. This means that this callback handler integrates with any JAAS LoginModule that handles X500 principals.

You can wire up a JaasCertificateValidationCallbackHandler as follows:

<bean id="jaasValidationHandler"
    class="org.springframework.ws.soap.security.xwss.callback.jaas.JaasCertificateValidationCallbackHandler">
    <property name="loginContextName">MyLoginModule</property>
</bean>

In this case, the callback handler uses the LoginContext named "MyLoginModule". This module should be defined in your jaas.config file, and should be able to authenticate against X500 principals.

7.5. Digital Signatures

The digital signature of a message is a piece of information based on both the document and the signer's private key. There are two main tasks related to signatures in WS-Security: verifying signatures and signing messages.

7.5.1. Verifying Signatures

Just like certificate-based authentication, a signed message contains a BinarySecurityToken, which contains the certificate used to sign the message. Additionally, it contains a SignedInfo block, which indicates what part of the message was signed.

To make sure that all incoming SOAP messages carry a BinarySecurityToken, the security policy file should contain a RequireSignature element. It can also contain a SignatureTarget element, which specifies the target message part which was expected to be signed, and various other subelements. You can also define the private key alias to use, whether to use a symmetric instead of a private key, and many other properties. You can find a reference of possible child elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    <xwss:RequireSignature requireTimestamp="false"/>
</xwss:SecurityConfiguration>

If the signature is not present, the XwsSecurityInterceptor will return a SOAP Fault to the sender. If it is present, it will fire a SignatureVerificationKeyCallback to the registered handlers. Within Spring-WS, there are is one class which handles this particular callback: the KeyStoreCallbackHandler.

7.5.1.1. KeyStoreCallbackHandler

As described in Section 7.3.3, “KeyStoreCallbackHandler”, the KeyStoreCallbackHandler uses a java.security.KeyStore for handling various cryptographic callbacks, including signature verification. For signature verification, the handler uses the trustStore property:

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="trustStore" ref="trustStore"/>
    </bean>

    <bean id="trustStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:org/springframework/ws/soap/security/xwss/test-truststore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

7.5.2. Signing Messages

When signing a message, the XwsSecurityInterceptor adds the BinarySecurityToken to the message, and a SignedInfo block, which indicates what part of the message was signed.

To sign all outgoing SOAP messages, the security policy file should contain a Sign element. It can also contain a SignatureTarget element, which specifies the target message part which was expected to be signed, and various other subelements. You can also define the private key alias to use, whether to use a symmetric instead of a private key, and many other properties. You can find a reference of possible child elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
	<xwss:Sign includeTimestamp="false" />
</xwss:SecurityConfiguration>

The XwsSecurityInterceptor will fire a SignatureKeyCallback to the registered handlers. Within Spring-WS, there are is one class which handles this particular callback: the KeyStoreCallbackHandler.

7.5.2.1. KeyStoreCallbackHandler

As described in Section 7.3.3, “KeyStoreCallbackHandler”, the KeyStoreCallbackHandler uses a java.security.KeyStore for handling various cryptographic callbacks, including signing messages. For adding signatures, the handler uses the keyStore property. Additionally, you must set the privateKeyPassword property to unlock the private key used for signing.

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="keyStore" ref="keyStore"/>
        <property name="privateKeyPassword" value="changeit"/>
    </bean>

    <bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:keystore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

7.6. Encryption and Decryption

When encrypting, the message is transformed into a form that can only be read with the appropriate key. The message can be decrypted to reveal the original, readable message.

7.6.1. Decryption

To decrypt incoming SOAP messages, the security policy file should contain a RequireEncryption element. This element can further carry a EncryptionTarget element which indicates which part of the message should be encrypted, and a SymmetricKey to indicate that a shared secret instead of the regular private key should be used to decrypt the message. You can read a description of the other elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    <xwss:RequireEncryption />
</xwss:SecurityConfiguration>

If an incoming message is not encrypted, the XwsSecurityInterceptor will return a SOAP Fault to the sender. If it is present, it will fire a DecryptionKeyCallback to the registered handlers. Within Spring-WS, there is one class which handled this particular callback: the KeyStoreCallbackHandler.

7.6.1.1. KeyStoreCallbackHandler

As described in Section 7.3.3, “KeyStoreCallbackHandler”, the KeyStoreCallbackHandler uses a java.security.KeyStore for handling various cryptographic callbacks, including decryption. For decryption, the handler uses the keyStore property. Additionally, you must set the privateKeyPassword property to unlock the private key used for decryption. For decryption based on symmetric keys, it will use the symmetricStore.

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="keyStore" ref="keyStore"/>
        <property name="privateKeyPassword" value="changeit"/>
    </bean>

    <bean id="keyStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:keystore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>

7.6.2. Encryption

To encrypt outgoing SOAP messages, the security policy file should contain a Encrypt element. This element can further carry a EncryptionTarget element which indicates which part of the message should be encrypted, and a SymmetricKey to indicate that a shared secret instead of the regular private key should be used to decrypt the message. You can read a description of the other elements here.

<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
    <xwss:Encrypt />
</xwss:SecurityConfiguration>

The XwsSecurityInterceptor will fire a EncryptionKeyCallback to the registered handlers in order to retrieve the encryption information. Within Spring-WS, there is one class which handled this particular callback: the KeyStoreCallbackHandler.

7.6.2.1. KeyStoreCallbackHandler

As described in Section 7.3.3, “KeyStoreCallbackHandler”, the KeyStoreCallbackHandler uses a java.security.KeyStore for handling various cryptographic callbacks, including encryption. For encryption based on public keys, the handler uses the trustStore property. For encryption based on symmetric keys, it will use the symmetricStore.

<beans>
    <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler">
        <property name="trustStore" ref="trustStore"/>
    </bean>

    <bean id="trustStore" class="org.springframework.ws.soap.security.support.KeyStoreFactoryBean">
        <property name="location" value="classpath:truststore.jks"/>
        <property name="password" value="changeit"/>
    </bean>
</beans>