JAX-RPC Handlers
One nice feature of JAX-RPC is the support for Handlers, which follow the Intercepting Filter design pattern. The 1.1 specification support SOAP protocol handlers, while the 1.2 specification makes a further distinction between Logical and Protocol Handlers. I like the idea of being able to plug Handlers in series to perform functions like logging, auditing, and security operations.
In this case, I was trying to create my first Handler which would restrict access to the service to trusted hosts. This is pretty simple in principle: inspect the ServletRequest for the remote address and verify that it is trusted.
I had a hell of a time finding documentation on how to specify server Handlers. I finally got it straightened out. I needed to modify the config.xml file used by the wscompile process. Here's what the config.xml looked like when I was done (names changed to protect my employer):
<?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http:///xml/ns/jax-rpc/ri/config"> <service name="MyService" targetNamespace="urn://MyService/wsdl" typeNamespace="urn://MyService/types" packageName="foo"> <interface name="foo.MyService" servantName="foo.MyServiceImpl"/> <handlerChains> <chain runAt="server"> <handler className="foo.handlers.TrustedHostsHandler"/> </chain> </handlerChains> </service> </configuration>
Then, the TrustedHostsHandler class overrode the handleRequest method in the Handler interface in order to inspect the remote host's IP. Here are the relevent sections:
public class TrustedHostsHandler extends GenericHandler { private static final String SERVLET_CONTEXT_CLASS = "com.sun.xml.rpc.server.http.HttpServletRequest"; private HandlerInfo config; public TrustedHostsHandler() { } public void init(HandlerInfo config) { assert null != config : "HandlerInfo argument was unexpectedly null"; this.config = config; } public QName[] getHeaders() { return config.getHeaders(); } public boolean handleRequest(MessageContext msgContext) { assert null != msgContext : "MessageContext argument unexpectedly null"; ServletRequest req = (ServletRequest) msgContext.getProperty(SERVLET_CONTEXT_CLASS); assert null != req : "ServletRequest unexpectedly null"; boolean result = false; String remoteAddress = req.getRemoteAddr(); if ((null != remoteAddress) && isTrusted(remoteAddress)) { result = true; } return result; } }
