WSS4J security is triggered through interceptors that are added to the service and client individually or as required. These interceptors allow you to perform the most common WS-Security related processes:
Pass authentication tokens between services.
Encrypt messages or parts of messages.
Sign messages.
Timestamp messages.
Interceptors can be added either programmatically or through the Spring xml configuration of endpoints. For instance, on server side, you can configure signature and encryption in the jbossws-cxf.xml file this way:
Copy to ClipboardCopied!Toggle word wrapToggle overflow
This specifies the whole security configuration (including algorithms and elements to be signed or encrypted); moreover it references a properties file (bob.properties) providing the keystore-related information:
Copy to ClipboardCopied!Toggle word wrapToggle overflow
As you can see in the jbossws-cxf.xml file above, a keystore password callback handler is also configured; while the properties file has the password for the keystore, this callback handler is used to set password for each key (it has to match the one used when each key was imported in the store). Here is an example:
package org.jboss.test.ws.jaxws.samples.wsse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class KeystorePasswordCallback implements CallbackHandler
{
private Map<String, String> passwords = new HashMap<String, String>();
public KeystorePasswordCallback()
{
passwords.put("alice", "password");
passwords.put("bob", "password");
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String pass = passwords.get(pc.getIdentifer());
if (pass != null)
{
pc.setPassword(pass);
return;
}
}
}
public void setAliasPassword(String alias, String password)
{
passwords.put(alias, password);
}
}
package org.jboss.test.ws.jaxws.samples.wsse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class KeystorePasswordCallback implements CallbackHandler
{
private Map<String, String> passwords = new HashMap<String, String>();
public KeystorePasswordCallback()
{
passwords.put("alice", "password");
passwords.put("bob", "password");
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String pass = passwords.get(pc.getIdentifer());
if (pass != null)
{
pc.setPassword(pass);
return;
}
}
}
public void setAliasPassword(String alias, String password)
{
passwords.put(alias, password);
}
}
Copy to ClipboardCopied!Toggle word wrapToggle overflow
On the client side, you can similarly setup the interceptors programmatically; here is an excerpt of the client for the above described endpoint:
To deploy your web service endpoint, you need to package the following files along with your service implementation and WSDL contract:
The jbossws-cxf.xml descriptor.
The properties file.
The keystore file (if required for signature/encryption).
The keystore password callback handler class.
For instance, here are the archive contents for the signature and encryption sample (POJO endpoint) mentioned before:
jar -tvf target/test-libs/jaxws-samples-wsse-sign-encrypt.war
[cxf-tests]$ jar -tvf target/test-libs/jaxws-samples-wsse-sign-encrypt.war
0 Tue Jun 03 19:41:26 CEST 2008 META-INF/
106 Tue Jun 03 19:41:24 CEST 2008 META-INF/MANIFEST.MF
0 Tue Jun 03 19:41:26 CEST 2008 WEB-INF/
0 Tue Jun 03 19:41:26 CEST 2008 WEB-INF/classes/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/
1628 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/KeystorePasswordCallback.class
364 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/ServiceIface.class
859 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/ServiceImpl.class
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/
685 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/SayHello.class
1049 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/SayHelloResponse.class
2847 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/jbossws-cxf.xml
0 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/wsdl/
1575 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/wsdl/SecurityService.wsdl
641 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/wsdl/SecurityService_schema1.xsd
1820 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/bob.jks
311 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/classes/bob.properties
573 Tue Jun 03 19:41:24 CEST 2008 WEB-INF/web.xml
Copy to ClipboardCopied!Toggle word wrapToggle overflow
On client side, instead, you only need the properties and keystore files (assuming you set up the interceptors programmatically). You just need to deploy and test your WS-Security-enabled application.