Steps to implementing WS-Security...
1. Determine how to use the TSIK API
This will be our "hello world" starting point. Figure out how to take a soap document on the file system, encrypt it and decrypt it via the TSIK api so we get an understanding of how to use it.
2. Try it with a document which streams in
Download the code at https://stax2dom.dev.java.net/ and figure out how to use it. You'll need to start with an XMLStreamReader and end up with a document. Pseudocode:
XMLInputFactory factory = XMLInputFactory.getInstance();
XMLStreamReader reader = factory.createXMLStreamReader(inputStreamToFile);
....
// somehow take the reader and create a Document with the above library.
org.w3c.dom.Document doc = ...
3. Create a DocumentXMLStreamReader
In this step we're going to forget about encryption and decryption. After decryption we'll end up with a org.w3c.dom.Document. But XFire expects an XMLStreamReader javadoc. So we need to convert between the two.
public class DocumentXMLStreamReader implements XMLStreamReader { public DocumentXMLStreamReader(org.w3c.dom.Document doc) { .... } public int next() { // this would get events as it progressed down the document. } .... }
I've done this before with the XOM xml toolkit. Check out this example. There is also a unit test which shows how to use it.
4. Tie it into XFire
We're going to write a Handler which does the following
- takes the incoming XMLStreamReader, reads it into a document
- Decrypts the document
- Creates another XMLStreamReader from the document
Here's a little pseudo code:
public class WSSecurityInHandler extends AbstractHandler { public String getPhase() { Phase.PARSE; } public void invoke(MessageContext context) { Document doc = createDoc(context.getInMessage().getXMLStreamReader); decrypt(doc); XMLStreamReader reader = createStream(doc); context.getInMessage().setXMLStreamReader(reader); } }
A test service:
public class Echo { public String echo(string echo) { return echo; } }
and a unit test:
public class WSSecurityTest extends AbstractXFireTest { Service service; public void setUp() { // Creates a service from the echo class service = getServiceFactory().create(Echo.class); // Registers it getServiceRegistry().register(service); // Add in a WS-Security Handler service.addInHandler(new WSSecurityHandler()); } public void testService() { // sends a message to your service. the handler intercepts the document and decrypts org.codehaus.yom.Document response = invokeService("Echo", "/encrypted/document/on/the/classpath.xml"); // prints the response to System.out printNode(response); // Checks to make sure we get the echo'd response addNamespace("e", service.getServiceInfo().getName().getNamespace()); assertValid("//e:echoResponse", response); } }
The "/encrypted/document/on/the/classpath.xml" needs to be an encrypted version of this document which the WS-SecurityHandler can understand:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Body> <m:echo xmlns:m="NAMESPACE"> <m:in0>Yo Yo</m:in0> </m:echo> </env:Body> </env:Envelope>
where NAMESPACE is the namespace of your service. The namespace is constructed from the pacakge name. You can easily view this by adding a
System.out.println(service.getServiceInfo().getName().getNamespace());
to the above test.
