Frequently you‘ll want to authenticate your service. There are many possible ways to do this. We‘ll try to outline some here.
HTTP Authentication
HTTP authentication is one of the most straightforward ways to secure your service. You simply need to to configure your servlet container to require a username and password. If you are wondering how to configure your XFire client to send an HTTP username/password check out the documentation on the HTTP Transport.
SOAP Header authentication with JSR 181
You can also send SOAP headers which container username/password information. This is quite simple with JSR 181. You simply need to create a class that contains the username and password:
public class UserToken { private String username; private String password; public String getUsername() { return username; }; public void setUsername(String username) { this.username = username; } public String getPassword() { return password; }; public void setPassword(String password) { this.password = password; } }
Then write your service class so that it takes this token:
public void someOperation(String data, @WebParam(header=true) UserToken token) { authenticate(token) // do your normal request here }
SOAP Header Authentication with Handlers
Often you will want to authenticate use of your service based on particular Headers in the SOAP Message. Say for example we have a header like the following:
<AuthenticationToken xmlns="urn:yourapp:authentication"> <Username>test</Username> <Password>123</Password> </AuthenticationToken>
We can easily write a Handler to process this information.
import org.codehaus.xfire.MessageContext; import org.codehaus.xfire.handler.AbstractHandler; import org.codehaus.yom.Element; public class AuthenticationHandler extends AbstractHandler { private final static String TOKEN_NS = "urn:yourapp:authentication"; public void invoke(MessageContext context) throws XFireFault { if (context.getInMessage().getHeader() == null) { throw new XFireFault("Request must include company authentication token.", XFireFault.SENDER); } Element token = context.getInMessage().getHeader().getFirstChildElement("AuthenticationToken", TOKEN_NS); if (token == null) { throw new XFireFault("Request must include authentication token.", XFireFault.SENDER); } String username = token.getFirstChildElement("Username", TOKEN_NS).getValue(); String password = token.getFirstChildElement("Password", TOKEN_NS).getValue(); try { // Do some authentication.... .... // we‘ve authenticated, now put the Company object in the context context.setProperty(COMPANY_KEY, company); } catch (Exception e) { throw new XFireFault("Invalid username/password.", XFireFault.SENDER); } } }
Client Authentication Handler
To make authentication to work, you also need to add the authentication information from the client.
One way to do it is by adding an out handler to your port via the XFireProxy and add the requisite tokens there.
A lot of the info below was taken as is from this blog: http://www./page/hexbinary/20051130
Also, all of the information below is true as of XFire 1.1-beta.
Create a ClientAuthenticationHandler like so:
public class ClientAuthenticationHandler extends AbstractHandler { private String username = null; private String password = null; public ClientAuthenticationHandler() { } public ClientAuthenticationHandler(String username,String password) { this.username = username; this.password = password; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void invoke(MessageContext context) throws Exception { final Namespace ns = Namespace.getNamespace("http://user.mynamesspace.com"); Element el = new Element("header",ns); context.getOutMessage().setHeader(el); Element auth = new Element("AuthenticationToken", ns); Element username_el = new Element("Username",ns); username_el.addContent(username); Element password_el = new Element("Password",ns); password_el.addContent(password); auth.addContent(username_el); auth.addContent(password_el); el.addContent(auth); } }
Now you need to add this authentication handler to the out handler of your client. One way to do this is programmatically:
MyXFireClient rsc = new MyXFireClient(); MyPortType myType = rsc.getServiceHttpPort(); XFireProxy proxy = (XFireProxy)Proxy.getInvocationHandler(myType); Client client = proxy.getClient(); client.addOutHandler(new ClientAuthenticationHandler("myUserName","myPassword"));
And you‘re done! Authenticating this way will add the requisite headers to your service.
WS-Security
WS-Security provides a Username/Password token that can be used. Check out the WS-Security instructions for more information.