Dynamic SOAP Header Injection With Spring Integration

When I discussed dynamic API endpoint resolution in my previous post, I mentioned that some services might require security headers. This makes creating a generic service a tad bit more complicated but there are ways around it. In this post I’ll talk about how to add a Web Service Security (WSSE) header, a custom (vendor specific) header or both to an outgoing web service request.
Once again, I’ll approach it from the angle of a (can’t be bothered) developer who doesn’t want to open up a new development track just because one service provider decided to define their own header.

Adding Headers to Outbound SOAP Requests

Just to jog your memory, our final SOAP outbound gateway looked something like this:

This caters for a simple implementation though: one which doesn’t require any headers at all. However, adding headers isn’t that difficult either. You just need to throw an interceptor into the mix like so:

Let’s look at the implementation of the headers more closely, starting with WSSE headers.

Adding WSSE Headers

Spring Integration makes it extremely easy to add WSSE headers to outgoing SOAP requests with their Wss4jSecurityInterceptor. The simplest implementation is to define the bean in the Spring context (it doesn’t necessarily have to be in the same file as the SOAP outbound flow) and set the necessary properties. A simple example requiring only a username and password is:

(See this excellent post by Mark Serrano if you want a more in – depth description of the Wss4jSecurityInterceptor).
Forgetting about dynamic endpoints for the moment, this is really all you need. Your credentials could be entered directly in the bean definition (not advised) or placed in a properties file (still not advised…plain text!). In which case, your outbound gateway would look like so:

However, we have chosen a bolder endeavour, “all for one and one for all”! So things get a bit more complicated here.
The first change I want to make is to add an ID to let us know which set of credentials we need to fetch. We’ll call this property “security_id” and pass it to the flow as an HTTP header as shown in the previous post:

Or, if you prefer, as a request parameter

Now, this is where I used a bit of a workaround. The SOAP message is sent to the interceptor wrapped in a message context object. This object has a properties map but I couldn’t for the life of me figure out how to set properties before writing this post. In case you’ve already figured out how to set them, I’ll show you how to use that method instead (although if you can figure out how to set it you probably don’t need my help on the easier part :P). In my case, I appended the identifier to my SOAP action like so:

Now we know which credentials to load, let’s dive into the interceptor!

Custom WSSE Interceptor

Seeing how much effort the Spring team put into creating their Wss4jSecurityInterceptor (and how lazy I am of course), I couldn’t possibly bring myself to shun their work and create my own from scratch. So, as the object oriented programmer I am, I inherited ;). My class is shown below:

The key here is just to make sure the necessary properties are set BEFORE calling Wss4jSecurityInterceptor’s initializeRequestData method. That way, you can inject your credentials (and decrypt them if they were stored encrypted in a database for example) and then let Spring handle the work of actually creating the header.

So that’s it for adding a WSSE header…but how about a custom one?

Adding a Custom SOAP Header

The process here is generally the same as above. Make sure you pass any data you would need in order to determine which exact header you need to generate. Then set the interceptor to your custom header generator class:

And create your CustomHeaderInjector class (this class will implement the org.springframework.ws.client.support.interceptor.ClientInterceptor interface but the only method you’ll really need to implement is handleRequest):

And that’s it for adding a custom header!

Two Headers Are Better Than One?

The final scenario I want to discuss is where the client requires BOTH their own custom header as well as a WSSE header. Don’t snort at me now, this is an actual use case I ran into! Thankfully, there’s a simple way of achieving this. Remember the “interceptor” attribute of the outbound gateway that took a bean reference? Well, you can use the “interceptors” attribute instead and pass it a list. Here’s how it’ll look:

Note that (in my implementation at least) the order of the interceptors is preserved. This is important to me because I’m not sure whether or not my custom header interceptor would overwrite the WSSE header if it was executed after. Spring’s WSS4J interceptor however maintains my custom header while adding its own so everything is just peachy!

Summary

That’s all for today. I discussed how to add WSSE headers with dynamic credential injection and custom SOAP headers to outbound SOAP requests. We also looked at a combination of both. Hopefully I’m not the only one crazy enough to do this and this post will actually be of help to someone else. Either way, I’m out!

Leave a Comment

Your email address will not be published. Required fields are marked *

captcha * Time limit is exhausted. Please reload the CAPTCHA.