Last year I wrote an article on Web Services authentication. At the time Axis 1.x was used for the examples, but by now Axis 2 has been released, and I want to talk about the changes that this new version brings about. The first article is referenced repeatedly, so you may want to skim it at least before proceeding with this one.
An important improvement in Axis 2 is that WS-Security is now more tightly integrated with it. It used to be that the WSS4J library (which implements WS-Security) was a separate project, and needed to be added manually to an Axis installation, but no more. An Axis module called Rampart wraps the WSS4J functionality, and can be added to a base Axis installation with little effort.
Because WS-Security is so readily available now, it should be the preferred method of authentication. HTTP authentication as described in the first article can still be used (since Axis is implemented as a servlet in a web app), but it should be considered obsolete and be phased out. I will not discuss it here. Nor will I address the Tomcat Realm integration, because nothing has changed in that regard.
I will present two kinds of WS clients, one using the SAAJ API which was also discussed in the first article, the other one using Axis own API. Axis 2 no longer supports JAX-RPC, so that client is missing here (JAX-RPC is being replaced by JAX-WS, but that's not yet supported by Axis).
A couple of steps need to taken before we can experiment with authentication.
The example files discussed in this article can be downloaded here: axis2-auth.zip
Axis 2 needs to be installed and 'happy'; this can be checked on
the Axis installation home page (http://localhost:8080/axis2/) under the
Validate link. Also, the
AXIS2_HOME environment variable needs to set to the
directory where the Axis distribution is installed.
Next, the WS-Security module Rampart needs to be installed. For this, copy the rampart-1.1.mar and addressing-1.1.mar files that are part of the example download to the WEB-INF/modules directory and restart the Axis web app. Now Rampart should be listed on the Axis Admin page (http://localhost:8080/axis2/axis2-admin/, default username is 'admin' with password 'axis2') under Available Modules.
Finally, the example web service must be installed. Copy the FibonacciService.aar file into the WEB-INF/services directory and once more restart Axis. FibonaciService should now be listed under Available Services, and it should report that rampart-1.1 is an engaged module for it. (Alternatively, the service archive file can also be uploaded through the Upload Service link on the Admin web page.)
Now we're ready to play. Open a command prompt in the directory containing the examples,
and start the tcpmon application by typing
This will show the SOAP requests and responses in a convenient way.
Then run the SAAJ client by typing
ant test-saaj -Dn=15 -Dport=8079.
The 'n' parameter is the input to the
Fibonacci function. You can choose a different one, but then the result will
not be 610. The port 8079 is the one used by the tcpmon tool; use 8080 if you
want to go straight to the Axis web app, thus not monitoring the call. (Note
that the SAAJ client also logs the request and response to the console; I've
not found a way to turn that off.)
All the interesting WS-Security information is in the
element that's part of the SOAP header. It can have several child elements;
in this case,
wsse:UsernameToken are present.
Why these, and what do they mean? WS-Security can perform 4 different actions:
Timestamping, Authentication, Encryption and Signature. Here, the first two are
used. A timestamp is used to indicate how long the supplied credentials (here:
the username/password) are valid, and the service is supposed to reject them if
it thinks that they are too old. Since we're focusing on the authentication,
I'll not address timestamps in any more detail. They're optional in any case.
The username token essentially consists of the username and the password, which is digested in this case (meaning it can't be recovered should the message be intercepted).
The actual body is rather
short, carrying the
calculateFibonacci call with parameter 15. The response
carries no WS-security information, just the
calculateFibonacciResponse with result 610.
<?xml version='1.0' encoding='UTF-8'> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-6557466"> <wsu:Created>2007-04-30T18:29:15.687Z</wsu:Created> <wsu:Expires>2007-04-30T18:34:15.687Z</wsu:Expires> </wsu:Timestamp> <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-4055741"> <wsse:Username>wsuser</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-username-token-profile-1.0#PasswordDigest"> YaVaSHBtqjGDWoHEdB1zuB3CR68=</wsse:Password> <wsse:Nonce>E62qDYhYVoUkJSukJGrvdA==</wsse:Nonce> <wsu:Created>2007-04-30T18:29:15.665Z</wsu:Created> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> <ns1:calculateFibonacci xmlns:ns1="http://fibonacci/xsd"> <in0>15</in0> </ns1:calculateFibonacci> </soapenv:Body> </soapenv:Envelope> <?xml version='1.0' encoding='UTF-8'> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header/> <soapenv:Body> <ns:calculateFibonacciResponse xmlns:ns="http://fibonacci/xsd"> <ns:return>610</ns:return> </ns:calculateFibonacciResponse> </soapenv:Body>
The WS-Security options are controlled by the
the client config file
conf/axis2.xml. The relevant section is this:
<parameter name="OutflowSecurity"> <action> <items>UsernameToken Timestamp</items> <user>wsuser</user> <passwordCallbackClass> fibonacci.PWHandlerClient </passwordCallbackClass> <!-- <passwordType>PasswordText</passwordType> --> <!-- <timeToLive>10</timeToLive> --> </action> </parameter>
It specifies that a
UsernameToken and a
Timestamp should be
optional, as stated above). Furthermore, it tells Axis which username to use,
and which class will supply the password that goes along with this username.
Other options (commented out here) include the use of a cleartext password
(instead of the digested one that is created by default), and how to specify a
longer time-to-live for the timestamp (10 seconds instead of the default 5).
The remainder of the file contains the non-WS-Security setup of Axis.
In addition to the
conf/axis.xml file, both
the Addressing and Rampart Axis module need to be available on
the client side. The two APIs differ slightly in how to tell the application
where to find these. For the SAAJ client, two system properties (
axis2.xml) must be set, while for the
Axis API, these can be set programmatically (and thus are passed in via command
line parameters). The
build.xml file shows how to do that for both.
The server side config file (
resources/META-INF/services.xml) has a
similar section that specifies which WS-Security actions to perform, and which
class to call to check the password:
<parameter name="InflowSecurity"> <action> <items>UsernameToken Timestamp</items> <passwordCallbackClass> fibonacci.PWHandlerServer </passwordCallbackClass> </action> </parameter>
The Axis API client produces
the same request and response; it is run via
ant test-axis2 -Dn=15 -Dport=8079.
Files in the examples download
axis2.log - log file written by the Axis client classes build classes - where the compiled Java classes are kept FibonacciService.aar - service archive for deployment, created by ant generate.service FibonacciService.wsdl - WSDL description of the service, created by ant generate.wsdl build.xml - Ant build file conf axis2.xml - client side deployment descriptor log4j.properties - log4j config file modules addressing-1.1.mar - Axis module that implements WS-Addressing rampart-1.1.mar - Axis module that implements WS-Security (These versions are appropriate for Axis2 1.1; if you're using a different version, you should download its associated module files from the Axis2 web site.) resources META-INF services.xml - server side deployment descriptor, goes into FibonacciService.aar src fibonacci Axis2Client.java - WS client using the Axis API FibonacciService.java - the class implementing the service PWHandlerClient.java - handles passwords on the client PWHandlerServer.java - handles passwords on the server SAAJClient.java - WS client using the SAAJ API. It has a commented-out section that shows how to set and use arbitrary SOAP headers. tcpmon.jar - standalone Swing app that can act as a proxy for web service requests and responses, and shows those in a structured way