Upload
nilanjan-bhattacharya
View
261
Download
3
Embed Size (px)
Citation preview
Peter Arockiaraj
Can you hear me now?…Good!
HomeAbout Me
Developing CXF WS-Security with SAML
4 Votes
Introduction
In this article we are going to develop a web service by using Spring and CXF with WS-Security (SAML).
This article provides steps (step by step) to create & deploy web services by usingSpring and CXF with
WS-Security (SAML). Please go through below to find sample web services.
Software Requirements
EClipse (Java IDE)- Optional1.
CXF Jars (Required for Compilation-Download from http://cxf.apache.org/download.html)2.
The Code
In this example, we are going to create a Hello service. In this example, we are going to use a code-first
approach for this service using JAX-WS annotations.
Creating Server and Client Certificates
For the Signature and Encryption actions, you’ll need to create a public & private key for the entities
involved. You can generate a key pair for the development environment via the following steps. Keep in mind
these will not be signed by an external authority like Verisign
Keytool is inbuild tool which is comes with jdk.
Follow the steps to create client and server certificates (Refer following site)
http://pa55word.wordpress.com/1.
When urgently you need some keystores and truststores to test out some security related java code this is a
useful bat file to have. Copy the code below and create a bat file. run it and you got your stuff.
keytool -genkey -alias serverkeys -keyalg RSA -keystore server.keystore -storepass changeit -keypass
changeit -dname “CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, ST=MYSTATE, C=MY”
keytool -export -alias serverkeys -keystore server.keystore -storepass changeit -file server.cer
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
1 of 67 6/22/2011 2:07 PM
keytool -genkey -alias clientkeys -keyalg RSA -keystore client.keystore -storepass changeit -keypass
changeit -dname “CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, S=MY
STATE, C=MY”
keytool -export -alias clientkeys -keystore client.keystore -storepass changeit -file client.cer
keytool -import -v -keystore client.truststore -storepass changeit -file server.cer
keytool -import -v -keystore server.truststore -storepass changeit -file client.cer
It generates a keystore called server.keystore with password changeit. Then it
creates server certificate server.cer.
Then it generates a keystore called client.keystore with password changeit. Creates a client certificate namedclient.cer
Next it imports server certificate into client truststore and client certificate into server truststore.
These are self signed certificates. Good for internal use. You can use open ssland create certificates. But this bat file is short and sweet for immediate use.
When you paste it you do have to be careful about keywords not getting split up like wordpress does.
Creating Server Application
Step 1: Download Following Jar files.
activation.jar
aopalliance-1.0.jar
commons-collections-3.2.jar
commons-lang-2.1.jar
commons-logging-1.1.jar
geronimo-activation-2.0.1.jar
geronimo-annotation_1.0_spec-1.1.jar
geronimo-javamail_1.4_mail-1.2.jar
geronimo-servlet_2.5_spec-1.1.jar
geronimo-ws-metadata_2.0_spec-1.1.1.jar
jaxb-api.jar
jaxb-api-2.0.jar
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
2 of 67 6/22/2011 2:07 PM
jaxb-impl-2.0.5.jar
jaxb-xjc.jar
jaxws-api.jar
mail.jar
neethi-2.0.jar
opensaml-1.0.1.jar
saaj-api.jar
saaj-impl.jar
spring-beans-2.0.6.jar
spring-context-2.0.6.jar
spring-core-2.0.6.jar
spring-web-2.0.6.jar
stax-api-1.0.1.jar
velocity-1.5.jar
wsdl4j-1.6.1.jar
wstx-asl-3.2.1.jar
xalan-2[1].6.0.jar
xalan-2[1].7.0.jar
xml-resolver-1.2.jar
cxf-bundle-2.0.4-incubator.jar
XmlSchema-1.3.2.jar
wss4j-1.5.1.jar
keyexport.jar
pkcs12import.jar
security-plugin.jar
wss-provider-update.jar
xws-security_jaxrpc.jar
xws-security.jar
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
3 of 67 6/22/2011 2:07 PM
xmlsec-1.3.0.jar
Step 2: Create New Java project in eclipse (CXFSAMLSecurity).
Step 3: Create WEB-INF folder inside project folder.
Step 4: Create classes folder inside WEB-INF folder.
Step 5: Create lib folder inside WEB-INF folder.
Step 6: Copy all the jar file into lib folder.
Step 7: Add all jar files into classpath (In Eclipse set java build path->Libraries). Add set Default outputfolder into CXFSAMLSecurity/WEB-INF/classes
Step 8: Create Remote Interface IHello.java
package com.sungard.cxf.example.server;
import javax.jws.WebService;
@WebService
public interface IHello {
public String sayHello(String value);
}
Step 9: Create Implementation Class IHello_Impl.java
package com.sungard.cxf.example.server;
import javax.jws.WebService;
@WebService(endpointInterface = “com.sungard.cxf.example.server.IHello”)
public class IHello_Impl implements IHello {
public String sayHello(String value) {
return “You Said” + value;
}
}
Step 10: Create ServerSecurityEnvironmentHandler.java file to handle usernames and passwords. Here youhave to give server certificate, server trust certificate alias name for checking. Password is alias password.
Also you have to give client keystore file passwords also.
private String keyStorePassword = “changeit”;
private String trustStorePassword = “changeit”;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
4 of 67 6/22/2011 2:07 PM
else if (callbacks[i] instanceof WSPasswordCallback) {
System.out.println(“handle::WSPasswordCallback”);
WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];
cb.setPassword(“changeit”);
}
package com.sungard.cxf.example.server;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertPathBuilder;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
5 of 67 6/22/2011 2:07 PM
import org.apache.ws.security.WSPasswordCallback;
//import com.sun.org.apache.xml.internal.security.utils.RFC2253Parser;
import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
import com.sun.xml.wss.impl.callback.DecryptionKeyCallback;
import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import com.sun.xml.wss.impl.callback.SignatureKeyCallback;
import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;
import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
import com.sun.xml.wss.impl.misc.SecurityUtil;
/**
* A sample implementation of a CallbackHandler.
*/
public class ServerSecurityEnvironmentHandler implements CallbackHandler {
private KeyStore keyStore;
private KeyStore trustStore;
private String keyStorePassword = “changeit”;
private String trustStorePassword = “changeit”;
private static final UnsupportedCallbackException unsupported = new UnsupportedCallbackException(
null, “Unsupported Callback Type Encountered”);
public ServerSecurityEnvironmentHandler() throws Exception {
initTrustStore();
initKeyStore();
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
System.out.println(“Entered::ServerSecurityEnvironmentHandler::handle”);
for (int i = 0; i < callbacks.length; i++) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
6 of 67 6/22/2011 2:07 PM
System.out.println(“handle::For-1″);
if (callbacks[i] instanceof PasswordValidationCallback) {
System.out.println(“handle::PasswordValidationCallback”);
PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];
if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
System.out.println(“handle::PlainTextPasswordRequest”);
cb.setValidator(new PlainTextPasswordValidator());
} else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
System.out.println(“handle::DigestPasswordRequest”);
PasswordValidationCallback.DigestPasswordRequest request =(PasswordValidationCallback.DigestPasswordRequest) cb
.getRequest();
String username = request.getUsername();
if (“Ron”.equals(username)) {
request.setPassword(“noR”);
cb
.setValidator(new PasswordValidationCallback.DigestPasswordValidator());
}
} else {
throw unsupported;
}
} else if (callbacks[i] instanceof TimestampValidationCallback) {
System.out.println(“handle::TimestampValidationCallback”);
TimestampValidationCallback cb = (TimestampValidationCallback) callbacks[i];
cb.setValidator(new DefaultTimestampValidator());
} else if (callbacks[i] instanceof SignatureVerificationKeyCallback) {
System.out.println(“handle::SignatureVerificationKeyCallback”);
SignatureVerificationKeyCallback cb = (SignatureVerificationKeyCallback) callbacks[i];
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
7 of 67 6/22/2011 2:07 PM
if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
System.out.println(“handle::X509SubjectKeyIdentifierBasedRequest”);
// subject keyid request
SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request =(SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
.getRequest();
X509Certificate cert = getCertificateFromTrustStore(request
.getSubjectKeyIdentifier());
request.setX509Certificate(cert);
} else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) {
// issuer serial request
System.out.println(“handle::X509IssuerSerialBasedRequest”);
SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request =(SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) cb
.getRequest();
X509Certificate cert = getCertificateFromTrustStore(request
.getIssuerName(), request.getSerialNumber());
request.setX509Certificate(cert);
} else {
throw unsupported;
}
} else if (callbacks[i] instanceof SignatureKeyCallback) {
System.out.println(“handle::SignatureKeyCallback”);
SignatureKeyCallback cb = (SignatureKeyCallback) callbacks[i];
if (cb.getRequest() instanceof SignatureKeyCallback.DefaultPrivKeyCertRequest) {
System.out.println(“handle::DefaultPrivKeyCertRequest”);
// default priv key cert req
SignatureKeyCallback.DefaultPrivKeyCertRequest request =(SignatureKeyCallback.DefaultPrivKeyCertRequest) cb
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
8 of 67 6/22/2011 2:07 PM
.getRequest();
getDefaultPrivKeyCert(request);
} else if (cb.getRequest() instanceof SignatureKeyCallback.AliasPrivKeyCertRequest) {
System.out.println(“handle::AliasPrivKeyCertRequest”);
SignatureKeyCallback.AliasPrivKeyCertRequest request =
(SignatureKeyCallback.AliasPrivKeyCertRequest) cb
.getRequest();
String alias = request.getAlias();
try {
X509Certificate cert = (X509Certificate) keyStore
.getCertificate(alias);
request.setX509Certificate(cert);
// Assuming key passwords same as the keystore password
PrivateKey privKey = (PrivateKey) keyStore.getKey(
alias, keyStorePassword.toCharArray());
request.setPrivateKey(privKey);
} catch (Exception e) {
System.out.println(“handle::AliasPrivKeyCertRequest::Exception”);
throw new IOException(e.getMessage());
}
} else {
System.out.println(“handle::AliasPrivKeyCertRequest::Exception::own::1″);
throw unsupported;
}
} else if (callbacks[i] instanceof DecryptionKeyCallback) {
DecryptionKeyCallback cb = (DecryptionKeyCallback) callbacks[i];
System.out.println(“handle::DecryptionKeyCallback”);
if (cb.getRequest() instanceof DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
9 of 67 6/22/2011 2:07 PM
System.out.println(“handle::X509SubjectKeyIdentifierBasedRequest”);
DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request =
(DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
.getRequest();
byte[] ski = request.getSubjectKeyIdentifier();
PrivateKey privKey = getPrivateKey(ski);
request.setPrivateKey(privKey);
} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBasedRequest) {
System.out.println(“handle::X509IssuerSerialBasedRequest”);
DecryptionKeyCallback.X509IssuerSerialBasedRequest request =(DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb
.getRequest();
String issuerName = request.getIssuerName();
BigInteger serialNumber = request.getSerialNumber();
PrivateKey privKey = getPrivateKey(issuerName, serialNumber);
request.setPrivateKey(privKey);
} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBasedRequest) {
System.out.println(“handle::X509CertificateBasedRequest”);
DecryptionKeyCallback.X509CertificateBasedRequest request =(DecryptionKeyCallback.X509CertificateBasedRequest) cb
.getRequest();
X509Certificate cert = request.getX509Certificate();
PrivateKey privKey = getPrivateKey(cert);
request.setPrivateKey(privKey);
} else {
System.out.println(“handle::X509CertificateBasedRequest::Exception::own:2″);
throw unsupported;
}
} else if (callbacks[i] instanceof EncryptionKeyCallback) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
10 of 67 6/22/2011 2:07 PM
EncryptionKeyCallback cb = (EncryptionKeyCallback) callbacks[i];
System.out.println(“handle::EncryptionKeyCallback”);
if (cb.getRequest() instanceof EncryptionKeyCallback.AliasX509CertificateRequest) {
System.out.println(“handle::AliasX509CertificateRequest”);
EncryptionKeyCallback.AliasX509CertificateRequest request =
(EncryptionKeyCallback.AliasX509CertificateRequest) cb
.getRequest();
String alias = request.getAlias();
if (alias == null) {
System.out.println(“handle::AliasX509CertificateRequest::read”);
// plugin code here to read the cert from the
// ThreadLocal
} else {
try {
System.out.println(“handle::AliasX509CertificateRequest:try”);
X509Certificate cert = (X509Certificate) trustStore
.getCertificate(alias);
request.setX509Certificate(cert);
} catch (Exception e) {
System.out.println(“handle::AliasX509CertificateRequest::Exception”);
throw new IOException(e.getMessage());
}
}
} else {
System.out.println(“handle::AliasX509CertificateRequest::Exception::own::3″);
throw unsupported;
}
} else if (callbacks[i] instanceof CertificateValidationCallback) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
11 of 67 6/22/2011 2:07 PM
System.out.println(“handle::CertificateValidationCallback”);
CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];
cb.setValidator(new X509CertificateValidatorImpl());
} else if (callbacks[i] instanceof CertificateValidationCallback) {
System.out.println(“handle::CertificateValidationCallback”);
CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];
cb.setValidator(new X509CertificateValidatorImpl());
} else if (callbacks[i] instanceof WSPasswordCallback) {
System.out.println(“handle::WSPasswordCallback”);
WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];
System.out.println(“handle::cb.getPassword()”+cb.getPassword());
cb.setPassword(“changeit”);
} else {
System.out.println(“handle::CallBack Class Name::”+callbacks[i].getClass().getName());
System.out.println(“handle::CertificateValidationCallback::Exception::own::4″);
throw unsupported;
}
}
System.out.println(“Leaving::ServerSecurityEnvironmentHandler::handle”);
}
private void initTrustStore() throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::initTrustStore”);
try {
URL truststoreURL = SecurityUtil
.loadFromClasspath(“server-truststore.jks”);
trustStore = KeyStore.getInstance(“JKS”);
trustStore.load(truststoreURL.openStream(), trustStorePassword
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
12 of 67 6/22/2011 2:07 PM
.toCharArray());
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::initTrustStore”);
}
private void initKeyStore() throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::initKeyStore”);
try {
URL keystoreURL = SecurityUtil
.loadFromClasspath(“server-keystore.jks”);
keyStore = KeyStore.getInstance(“JKS”);
keyStore.load(keystoreURL.openStream(), keyStorePassword
.toCharArray());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::initKeyStore”);
}
private X509Certificate getCertificateFromTrustStore(byte[] ski)
throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore”);
try {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
13 of 67 6/22/2011 2:07 PM
Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate cert = trustStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
byte[] keyId = getSubjectKeyIdentifier(x509Cert);
if (keyId == null) {
// Cert does not contain a key identifier
continue;
}
if (Arrays.equals(ski, keyId)) {
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::1″);
return x509Cert;
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::2″);
return null;
}
private X509Certificate getCertificateFromTrustStore(String issuerName,
BigInteger serialNumber) throws IOException {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
14 of 67 6/22/2011 2:07 PM
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple”);
try {
Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate cert = trustStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser.normalize(x509Cert
.getIssuerDN().getName());
BigInteger thisSerialNumber = x509Cert.getSerialNumber();
if (thisIssuerName.equals(issuerName)
&& thisSerialNumber.equals(serialNumber)) {
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple::1″);
return x509Cert;
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getCertificateFromTrustStore::Multiple::2″);
return null;
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
15 of 67 6/22/2011 2:07 PM
public PrivateKey getPrivateKey(byte[] ski) throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey”);
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
byte[] keyId = getSubjectKeyIdentifier(x509Cert);
if (keyId == null) {
// Cert does not contain a key identifier
continue;
}
if (Arrays.equals(ski, keyId)) {
// Asuumed key password same as the keystore password
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::2″);
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
}
}
} catch (Exception e) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
16 of 67 6/22/2011 2:07 PM
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::2″);
return null;
}
public PrivateKey getPrivateKey(String issuerName, BigInteger serialNumber)
throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey::multiple”);
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser.normalize(x509Cert
.getIssuerDN().getName());
BigInteger thisSerialNumber = x509Cert.getSerialNumber();
if (thisIssuerName.equals(issuerName)
&& thisSerialNumber.equals(serialNumber)) {
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::multiple::1″);
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
17 of 67 6/22/2011 2:07 PM
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::multiple::1″);
return null;
}
public PrivateKey getPrivateKey(X509Certificate certificate)
throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getPrivateKey::certificate”);
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert != null && cert.equals(certificate))
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::certificate::1″);
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
18 of 67 6/22/2011 2:07 PM
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getPrivateKey::certificate::2″);
return null;
}
private void getDefaultPrivKeyCert(
SignatureKeyCallback.DefaultPrivKeyCertRequest request)
throws IOException {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getDefaultPrivKeyCert”);
String uniqueAlias = null;
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String currentAlias = (String) aliases.nextElement();
if (keyStore.isKeyEntry(currentAlias)) {
Certificate thisCertificate = keyStore
.getCertificate(currentAlias);
if (thisCertificate != null) {
if (thisCertificate instanceof X509Certificate) {
if (uniqueAlias == null) {
uniqueAlias = currentAlias;
} else {
// Not unique!
uniqueAlias = null;
break;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
19 of 67 6/22/2011 2:07 PM
}
}
}
}
}
if (uniqueAlias != null) {
request.setX509Certificate((X509Certificate) keyStore
.getCertificate(uniqueAlias));
request.setPrivateKey((PrivateKey) keyStore.getKey(uniqueAlias,
keyStorePassword.toCharArray()));
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getDefaultPrivKeyCert”);
}
private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {
System.out
.println(“Entered::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier”);
String SUBJECT_KEY_IDENTIFIER_OID = “2.5.29.14″;
byte[] subjectKeyIdentifier = cert
.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);
if (subjectKeyIdentifier == null)
return null;
try {
sun.security.x509.KeyIdentifier keyId = null;
sun.security.util.DerValue derVal = new sun.security.util.DerValue(
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
20 of 67 6/22/2011 2:07 PM
new sun.security.util.DerInputStream(subjectKeyIdentifier)
.getOctetString());
keyId = new sun.security.x509.KeyIdentifier(derVal.getOctetString());
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::1″);
return keyId.getIdentifier();
} catch (NoClassDefFoundError ncde) {
if (subjectKeyIdentifier == null)
return null;
byte[] dest = new byte[subjectKeyIdentifier.length - 4];
System.arraycopy(subjectKeyIdentifier, 4, dest, 0,
subjectKeyIdentifier.length – 4);
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::2″);
return dest;
} catch (java.io.IOException ex) {
// ignore
System.out
.println(“Leaving::ServerSecurityEnvironmentHandler::getSubjectKeyIdentifier::3″);
return null;
}
}
private class PlainTextPasswordValidator implements
PasswordValidationCallback.PasswordValidator {
public boolean validate(PasswordValidationCallback.Request request)
throws PasswordValidationCallback.PasswordValidationException {
System.out.println(“Entered::PlainTextPasswordValidator::validate”);
PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest =
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
21 of 67 6/22/2011 2:07 PM
(PasswordValidationCallback.PlainTextPasswordRequest) request;
if (“Ron”.equals(plainTextRequest.getUsername())
&& “noR”.equals(plainTextRequest.getPassword())) {
System.out
.println(“Leaving::PlainTextPasswordValidator::validate::true”);
return true;
}
System.out
.println(“Leaving::PlainTextPasswordValidator::validate::false”);
return false;
}
}
private class DefaultTimestampValidator implements
TimestampValidationCallback.TimestampValidator {
public void validate(TimestampValidationCallback.Request request)
throws TimestampValidationCallback.TimestampValidationException {
System.out.println(“Entered::DefaultTimestampValidator::validate”);
// validate timestamp creation and expiration time.
TimestampValidationCallback.UTCTimestampRequest utcTimestampRequest =(TimestampValidationCallback.UTCTimestampRequest) request;
SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(
“yyyy-MM-dd’T'HH:mm:ss’Z'”);
SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(
“yyyy-MM-dd’T'HH:mm:ss’.'SSS’Z'”);
Date created = null;
Date expired = null;
try {
try {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
22 of 67 6/22/2011 2:07 PM
created = calendarFormatter1.parse(utcTimestampRequest
.getCreated());
if (utcTimestampRequest.getExpired() != null)
expired = calendarFormatter1.parse(utcTimestampRequest
.getExpired());
} catch (java.text.ParseException pe) {
created = calendarFormatter2.parse(utcTimestampRequest
.getCreated());
if (utcTimestampRequest.getExpired() != null)
expired = calendarFormatter2.parse(utcTimestampRequest
.getExpired());
}
} catch (java.text.ParseException pe) {
throw new TimestampValidationCallback.TimestampValidationException(
pe.getMessage());
}
long maxClockSkew = utcTimestampRequest.getMaxClockSkew();
long timestampFreshnessLimit = utcTimestampRequest
.getTimestampFreshnessLimit();
// validate creation time
validateCreationTime(created, maxClockSkew, timestampFreshnessLimit);
// validate expiration time
if (expired != null)
validateExpirationTime(expired, maxClockSkew,
timestampFreshnessLimit);
System.out.println(“Leaving::DefaultTimestampValidator::validate”);
}
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
23 of 67 6/22/2011 2:07 PM
public void validateExpirationTime(Date expires, long maxClockSkew,
long timestampFreshnessLimit)
throws TimestampValidationCallback.TimestampValidationException {
System.out
.println(“Enterd::DefaultTimestampValidator::validateExpirationTime”);
Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),
maxClockSkew, false);
if (expires.before(currentTime)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The current time is ahead of the expiration time in Timestamp”);
}
System.out
.println(“Leaving::DefaultTimestampValidator::validateExpirationTime”);
}
public void validateCreationTime(Date created, long maxClockSkew,
long timestampFreshnessLimit)
throws TimestampValidationCallback.TimestampValidationException {
System.out
.println(“Enterd::DefaultTimestampValidator::validateCreationTime”);
Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,
timestampFreshnessLimit);
System.out.println(“Validate Creation time called current=” + current);
System.out.println(“Validate Creation time called created=” + created);
if (created.before(current)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The creation time is older than “
+ ” currenttime – timestamp-freshness-limit – max-clock-skew”);
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
24 of 67 6/22/2011 2:07 PM
Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),
maxClockSkew, true);
System.out.println(“Validate Creation time called currentTime=”
+ currentTime);
System.out.println(“Validate Creation time called created=” + created);
if (currentTime.before(created)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The creation time is ahead of the current time.”);
}
System.out
.println(“Leaving::DefaultTimestampValidator::validateCreationTime”);
}
private static Date getFreshnessAndSkewAdjustedDate(long maxClockSkew,
long timestampFreshnessLimit) {
System.out
.println(“Enterd::DefaultTimestampValidator::getFreshnessAndSkewAdjustedDate”);
Calendar c = new GregorianCalendar();
long offset = c.get(Calendar.ZONE_OFFSET);
if (c.getTimeZone().inDaylightTime(c.getTime())) {
offset += c.getTimeZone().getDSTSavings();
}
long beforeTime = c.getTimeInMillis();
long currentTime = beforeTime – offset;
System.out.println(“MaxSkew=” + maxClockSkew + ” freshness=”
+ timestampFreshnessLimit);
long adjustedTime = currentTime – maxClockSkew
- timestampFreshnessLimit;
c.setTimeInMillis(adjustedTime);
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
25 of 67 6/22/2011 2:07 PM
System.out
.println(“Leaving::DefaultTimestampValidator::getFreshnessAndSkewAdjustedDate”);
return c.getTime();
}
private static Date getGMTDateWithSkewAdjusted(Calendar c,
long maxClockSkew, boolean addSkew) {
System.out
.println(“Enterd::DefaultTimestampValidator::getGMTDateWithSkewAdjusted”);
long offset = c.get(Calendar.ZONE_OFFSET);
if (c.getTimeZone().inDaylightTime(c.getTime())) {
offset += c.getTimeZone().getDSTSavings();
}
long beforeTime = c.getTimeInMillis();
long currentTime = beforeTime – offset;
if (addSkew)
currentTime = currentTime + maxClockSkew;
else
currentTime = currentTime – maxClockSkew;
c.setTimeInMillis(currentTime);
System.out
.println(“Leaving::DefaultTimestampValidator::getGMTDateWithSkewAdjusted”);
return c.getTime();
}
private class X509CertificateValidatorImpl implements
CertificateValidationCallback.CertificateValidator {
public boolean validate(X509Certificate certificate)
throws CertificateValidationCallback.CertificateValidationException {
System.out
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
26 of 67 6/22/2011 2:07 PM
.println(“Enterd::X509CertificateValidatorImpl::validate”);
if (isSelfCert(certificate)) {
System.out
.println(“Leaving::X509CertificateValidatorImpl::validate::1″);
return true;
}
try {
certificate.checkValidity();
} catch (CertificateExpiredException e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
“X509Certificate Expired”, e);
} catch (CertificateNotYetValidException e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
“X509Certificate not yet valid”, e);
}
X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate(certificate);
PKIXBuilderParameters parameters;
CertPathBuilder builder;
try {
parameters = new PKIXBuilderParameters(trustStore, certSelector);
parameters.setRevocationEnabled(false);
builder = CertPathBuilder.getInstance(“PKIX”);
} catch (Exception e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
27 of 67 6/22/2011 2:07 PM
e.getMessage(), e);
}
try {
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
.build(parameters);
} catch (Exception e) {
e.printStackTrace();
System.out
.println(“Leaving::X509CertificateValidatorImpl::validate::2″);
return false;
}
System.out
.println(“Leaving::X509CertificateValidatorImpl::validate::3″);
return true;
}
private boolean isSelfCert(X509Certificate cert)
throws CertificateValidationCallback.CertificateValidationException {
System.out
.println(“Entered::X509CertificateValidatorImpl::isSelfCert”);
try {
if (keyStore == null)
initKeyStore();
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (keyStore.isKeyEntry(alias)) {
X509Certificate x509Cert = (X509Certificate) keyStore
.getCertificate(alias);
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
28 of 67 6/22/2011 2:07 PM
if (x509Cert != null) {
if (x509Cert.equals(cert))
System.out
.println(“Leaving::X509CertificateValidatorImpl::isSelfCert::1″);
return true;
}
}
}
System.out
.println(“Leaving::X509CertificateValidatorImpl::isSelfCert::2″);
return false;
} catch (Exception e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
e.getMessage(), e);
}
}
}
private String getContainerHome() {
System.out
.println(“Entered::X509CertificateValidatorImpl::getContainerHome”);
String _home = “”;
String fileSeparator = System.getProperty(“file.separator”);
String contHome = System.getProperty(“catalina.home”);
if (contHome != null) {
String isAS = System.getProperty(“com.sun.aas.instanceRoot”);
if (isAS != null) {
_home = contHome + fileSeparator + “..” + fileSeparator + “..”;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
29 of 67 6/22/2011 2:07 PM
} else {
_home = contHome;
}
} else {
_home = System.getProperty(“jwsdp.home”);
if (_home == null) {
_home = System.getProperty(“as.home”);
}
}
System.out
.println(“Leaving::X509CertificateValidatorImpl::getContainerHome”);
return _home;
}
}
Step 11: Create Interceptor class to handle soap requests ValidateUserTokenInterceptor.java.
package com.sungard.cxf.example.server;
import java.util.Vector;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
public class ValidateUserTokenInterceptor extends AbstractPhaseInterceptor {
public ValidateUserTokenInterceptor(String s) {
super(s);
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
30 of 67 6/22/2011 2:07 PM
public ValidateUserTokenInterceptor() {
super(Phase.UNMARSHAL);
}
public void handleMessage(Message message) {
System.out
.println(“Enterd ValidateUserTokenInterceptor::handleMessage”);
boolean userTokenValidated = false;
Vector result = (Vector) message
.getContextualProperty(WSHandlerConstants.RECV_RESULTS);
for (int i = 0; i < result.size(); i++) {
WSHandlerResult res = (WSHandlerResult) result.get(i);
for (int j = 0; j < res.getResults().size(); j++) {
WSSecurityEngineResult secRes = (WSSecurityEngineResult) res
.getResults().get(j);
if (secRes.getPrincipal() != null) {
System.out
.println(“ValidateUserTokenInterceptor::handleMessage::Class”
+ secRes.getPrincipal().getClass());
System.out
.println(“ValidateUserTokenInterceptor::handleMessage::ClassName”
+ secRes.getPrincipal().getClass()
.getName());
System.out
.println(“ValidateUserTokenInterceptor::handleMessage::Name”
+ secRes.getPrincipal().getName());
if (secRes.getPrincipal().getClass().getName().equals(
“org.apache.ws.security.WSUsernameTokenPrincipal”)) {
System.out
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
31 of 67 6/22/2011 2:07 PM
.println(“ValidateUserTokenInterceptor::handleMessage::WSUsernameTokenPrincipal”
+ secRes.getPrincipal().getName());
WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes
.getPrincipal();
System.out.println(“principal.isPasswordDigest”
+ principal.isPasswordDigest());
System.out.println(“principal.getNonce()”
+ principal.getNonce());
System.out.println(“principal.getPassword()”
+ principal.getPassword());
System.out.println(“principal.getCreatedTime()”
+ principal.getCreatedTime());
if (principal.getPassword() == null) {
throw new RuntimeException(
“Invalid Security Header”);
} else {
System.out
.println(“ValidateUserTokenInterceptor::handleMessage::userTokenValidated = true”);
userTokenValidated = true;
}
}
}
}
}
if (!userTokenValidated) {
throw new RuntimeException(“Security processing failed::Peter”);
}
System.out
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
32 of 67 6/22/2011 2:07 PM
.println(“Leaving ValidateUserTokenInterceptor::handleMessage”);
}
}
Step 12: Create beans.xml file to setup the application context for the server.
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:jaxws=”http://cxf.apache.org/jaxws”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd”>
<import resource=”classpath:META-INF/cxf/cxf.xml” />
<import resource=”classpath:META-INF/cxf/cxf-extension-soap.xml” />
<import resource=”classpath:META-INF/cxf/cxf-servlet.xml” />
<jaxws:endpoint id=”helloWorld”
implementor=”com.sungard.cxf.example.server.IHello_Impl”
address=”/HelloService”>
<jaxws:inInterceptors>
<bean id=”logIn”
/>
<bean id=”logOut”
/>
<bean
/>
<bean
>
<property name=”properties”>
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
33 of 67 6/22/2011 2:07 PM
<map>
<entry key=”action”
value=”UsernameToken SAMLTokenUnsigned” />
<entry key=”passwordType” value=”PasswordText” />
<entry key=”enableNamespacePrefixOptimization”
value=”true” />
<entry key=”disablePrettyXML” value=”true” />
<entry key=”sendXsiTypes” value=”true” />
<entry key=”sendMultiRefs” value=”true” />
<entry key=”sendXMLDeclaration” value=”true” />
<entry key=”passwordCallbackClass”
value=”com.sungard.cxf.example.server.ServerSecurityEnvironmentHandler” />
<entry key=”signaturePropFile”
value=”server_sign.properties”>
</entry>
</map>
</property>
</bean>
<bean
/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
Step 13: Create server_sign.properties under WEB-INF\classes folder to mention private keystore file details.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.file=server-keystore.jks
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
34 of 67 6/22/2011 2:07 PM
Step 14: Copy all keystore and certificate files under WEB-INF\classes folder.
Step 15: Create web.xml file
<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE web-app
PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
“http://java.sun.com/dtd/web-app_2_3.dtd”>
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
35 of 67 6/22/2011 2:07 PM
</web-app>
Step 16: Create ant folder inside project. And Create build.xml file inside ant folder.
<?xml version=”1.0″ encoding=”UTF-8″?>
<project basedir=”../” default=”archive”>
<target name=”archive”>
<jar destfile=”samlnormalsecurity.war”>
<fileset dir=”${basedir}”>
<include name=”**/*.class” />
<include name=”**/*.jks*” />
<include name=”**/*.properties*” />
</fileset>
<fileset dir=”${basedir}”>
<include name=”**/*.jar” />
</fileset>
<fileset dir=”${basedir}”>
<include name=”**/*.xml” />
<exclude name=”**/*build*” />
</fileset>
</jar>
</target>
</project>
Step 17: Run build.xml using Ant.
Step 18: Deploy samlnormalsecurity.war into Web/Application Server (Tomcat/JBoss).
Step 19: Verify application deployed successfully or by using following url.
http://localhost:8080/samlnormalsecurity/HelloService?wsdl
Step 20: Browser will show wsdl file our web service.
Creating Client Application.
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
36 of 67 6/22/2011 2:07 PM
Step 1: Create New Java project in Eclipse
Step 2: Create folder Structure as like above application
Step 3: Use same jar files used for Server application.
Step 4: Set all the jars files into classpath.
Step 5: Create Remote Interface in client (IHello.java) (You can use wsdl2java for creating same)
package com.sungard.cxf.example.server;
import javax.jws.WebService;
@WebService
public interface IHello {
public String sayHello(String value);
}
Step 6: Create ClientSecurityEnvironmentHandler.java for handling soap request in client side. Here you have
set the password what you are given client alias. You have tomention client ketstore passwords also here.
private String keyStorePassword = “changeit”;
private String trustStorePassword = “changeit”;
else if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];
System.out.println(“cb.getPassword()” + cb.getPassword());
cb.setPassword(“changeit”);
}
package com.sungard.cxf.example.server;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertPathBuilder;
import java.security.cert.Certificate;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
37 of 67 6/22/2011 2:07 PM
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.ws.BindingProvider;
import org.apache.ws.security.WSPasswordCallback;
import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
import com.sun.xml.wss.impl.callback.DecryptionKeyCallback;
import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import com.sun.xml.wss.impl.callback.SignatureKeyCallback;
import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;
import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
import com.sun.xml.wss.impl.misc.SecurityUtil;
/**
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
38 of 67 6/22/2011 2:07 PM
* A sample implementation of a CallbackHandler.
*/
public class ClientSecurityEnvironmentHandler implements CallbackHandler {
private KeyStore keyStore;
private KeyStore trustStore;
private String keyStorePassword = “changeit”;
private String trustStorePassword = “changeit”;
private static final UnsupportedCallbackException unsupported = new UnsupportedCallbackException(
null, “Unsupported Callback Type Encountered”);
public ClientSecurityEnvironmentHandler() throws Exception {
System.out.println(“Entered::ClientSecurityEnvironmentHandler”);
initTrustStore();
initKeyStore();
System.out.println(“Leaving::ClientSecurityEnvironmentHandler”);
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
System.out.println(“Entered::ClientSecurityEnvironmentHandler::handle”);
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof PasswordValidationCallback) {
PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];
if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
cb.setValidator(new PlainTextPasswordValidator());
} else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
PasswordValidationCallback.DigestPasswordRequest request =(PasswordValidationCallback.DigestPasswordRequest) cb
.getRequest();
String username = request.getUsername();
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
39 of 67 6/22/2011 2:07 PM
if (“Ron”.equals(username)) {
request.setPassword(“noR”);
cb
.setValidator(new PasswordValidationCallback.DigestPasswordValidator());
}
} else {
System.out
.println(“ClientSecurityEnvironmentHandler::Handle::1″);
throw unsupported;
}
} else if (callbacks[i] instanceof TimestampValidationCallback) {
TimestampValidationCallback cb = (TimestampValidationCallback) callbacks[i];
cb.setValidator(new DefaultTimestampValidator());
} else if (callbacks[i] instanceof SignatureVerificationKeyCallback) {
SignatureVerificationKeyCallback cb = (SignatureVerificationKeyCallback) callbacks[i];
if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
// subject keyid request
SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest request =
(SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
.getRequest();
X509Certificate cert = getCertificateFromTrustStore(request
.getSubjectKeyIdentifier());
request.setX509Certificate(cert);
} else if (cb.getRequest() instanceof SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) {
// issuer serial request
SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest request =
(SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest) cb
.getRequest();
X509Certificate cert = getCertificateFromTrustStore(request
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
40 of 67 6/22/2011 2:07 PM
.getIssuerName(), request.getSerialNumber());
request.setX509Certificate(cert);
} else {
System.out
.println(“ClientSecurityEnvironmentHandler::Handle::2″);
throw unsupported;
}
} else if (callbacks[i] instanceof SignatureKeyCallback) {
SignatureKeyCallback cb = (SignatureKeyCallback) callbacks[i];
if (cb.getRequest() instanceof SignatureKeyCallback.DefaultPrivKeyCertRequest) {
// default priv key cert req
SignatureKeyCallback.DefaultPrivKeyCertRequest request =
(SignatureKeyCallback.DefaultPrivKeyCertRequest) cb
.getRequest();
getDefaultPrivKeyCert(request);
} else if (cb.getRequest() instanceof SignatureKeyCallback.AliasPrivKeyCertRequest) {
SignatureKeyCallback.AliasPrivKeyCertRequest request =
(SignatureKeyCallback.AliasPrivKeyCertRequest) cb
.getRequest();
String alias = request.getAlias();
try {
X509Certificate cert = (X509Certificate) keyStore
.getCertificate(alias);
request.setX509Certificate(cert);
// Assuming key passwords same as the keystore password
PrivateKey privKey = (PrivateKey) keyStore.getKey(
alias, keyStorePassword.toCharArray());
request.setPrivateKey(privKey);
} catch (Exception e) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
41 of 67 6/22/2011 2:07 PM
throw new IOException(e.getMessage());
}
} else {
System.out
.println(“ClientSecurityEnvironmentHandler::Handle::3″);
throw unsupported;
}
} else if (callbacks[i] instanceof DecryptionKeyCallback) {
DecryptionKeyCallback cb = (DecryptionKeyCallback) callbacks[i];
if (cb.getRequest() instanceof DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) {
DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest request =
(DecryptionKeyCallback.X509SubjectKeyIdentifierBasedRequest) cb
.getRequest();
byte[] ski = request.getSubjectKeyIdentifier();
PrivateKey privKey = getPrivateKey(ski);
request.setPrivateKey(privKey);
} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509IssuerSerialBasedRequest) {
DecryptionKeyCallback.X509IssuerSerialBasedRequest request =
(DecryptionKeyCallback.X509IssuerSerialBasedRequest) cb
.getRequest();
String issuerName = request.getIssuerName();
BigInteger serialNumber = request.getSerialNumber();
PrivateKey privKey = getPrivateKey(issuerName, serialNumber);
request.setPrivateKey(privKey);
} else if (cb.getRequest() instanceof DecryptionKeyCallback.X509CertificateBasedRequest) {
DecryptionKeyCallback.X509CertificateBasedRequest request =
(DecryptionKeyCallback.X509CertificateBasedRequest) cb
.getRequest();
X509Certificate cert = request.getX509Certificate();
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
42 of 67 6/22/2011 2:07 PM
PrivateKey privKey = getPrivateKey(cert);
request.setPrivateKey(privKey);
} else {
System.out
.println(“ClientSecurityEnvironmentHandler::Handle::4″);
throw unsupported;
}
} else if (callbacks[i] instanceof EncryptionKeyCallback) {
EncryptionKeyCallback cb = (EncryptionKeyCallback) callbacks[i];
if (cb.getRequest() instanceof EncryptionKeyCallback.AliasX509CertificateRequest) {
EncryptionKeyCallback.AliasX509CertificateRequest request =
(EncryptionKeyCallback.AliasX509CertificateRequest) cb
.getRequest();
String alias = request.getAlias();
if (alias == null) {
// plugin code here to read the cert from the
// ThreadLocal
} else {
try {
X509Certificate cert = (X509Certificate) trustStore
.getCertificate(alias);
request.setX509Certificate(cert);
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
} else {
System.out
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
43 of 67 6/22/2011 2:07 PM
.println(“ClientSecurityEnvironmentHandler::Handle::5″);
throw unsupported;
}
} else if (callbacks[i] instanceof CertificateValidationCallback) {
CertificateValidationCallback cb = (CertificateValidationCallback) callbacks[i];
cb.setValidator(new X509CertificateValidatorImpl());
} else if (callbacks[i] instanceof UsernameCallback) {
UsernameCallback cb = (UsernameCallback) callbacks[i];
String username = (String) cb.getRuntimeProperties().get(
BindingProvider.USERNAME_PROPERTY);
System.out.println(“Got Username……… : ” + username);
cb.setUsername(username);
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback cb = (PasswordCallback) callbacks[i];
String password = (String) cb.getRuntimeProperties().get(
BindingProvider.PASSWORD_PROPERTY);
System.out.println(“Got Password……… : ” + password);
cb.setPassword(password);
} else if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback cb = (WSPasswordCallback) callbacks[i];
System.out.println(“cb.getPassword()” + cb.getPassword());
cb.setPassword(“changeit”);
} else {
System.out.println(callbacks[i].getClass().getName());
System.out
.println(“ClientSecurityEnvironmentHandler::Handle::6″);
throw unsupported;
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
44 of 67 6/22/2011 2:07 PM
}
}
private void initTrustStore() throws IOException {
try {
URL truststoreURL = SecurityUtil
.loadFromClasspath(“client-truststore.jks”);
trustStore = KeyStore.getInstance(“JKS”);
trustStore.load(truststoreURL.openStream(), trustStorePassword
.toCharArray());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private void initKeyStore() throws IOException {
try {
URL keystoreURL = SecurityUtil
.loadFromClasspath(“client-keystore.jks”);
keyStore = KeyStore.getInstance(“JKS”);
keyStore.load(keystoreURL.openStream(), keyStorePassword
.toCharArray());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private X509Certificate getCertificateFromTrustStore(byte[] ski)
throws IOException {
try {
Enumeration aliases = trustStore.aliases();
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
45 of 67 6/22/2011 2:07 PM
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate cert = trustStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
byte[] keyId = getSubjectKeyIdentifier(x509Cert);
if (keyId == null) {
// Cert does not contain a key identifier
continue;
}
if (Arrays.equals(ski, keyId)) {
return x509Cert;
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}
private X509Certificate getCertificateFromTrustStore(String issuerName,
BigInteger serialNumber) throws IOException {
try {
Enumeration aliases = trustStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
Certificate cert = trustStore.getCertificate(alias);
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
46 of 67 6/22/2011 2:07 PM
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
X509Certificate x509Cert = (X509Certificate) cert;
String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser
.normalize(x509Cert.getIssuerDN().getName());
BigInteger thisSerialNumber = x509Cert.getSerialNumber();
if (thisIssuerName.equals(issuerName)
&& thisSerialNumber.equals(serialNumber)) {
return x509Cert;
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}
public PrivateKey getPrivateKey(byte[] ski) throws IOException {
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
47 of 67 6/22/2011 2:07 PM
X509Certificate x509Cert = (X509Certificate) cert;
byte[] keyId = getSubjectKeyIdentifier(x509Cert);
if (keyId == null) {
// Cert does not contain a key identifier
continue;
}
if (Arrays.equals(ski, keyId)) {
// Asuumed key password same as the keystore password
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}
public PrivateKey getPrivateKey(String issuerName, BigInteger serialNumber)
throws IOException {
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert == null || !”X.509″.equals(cert.getType())) {
continue;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
48 of 67 6/22/2011 2:07 PM
}
X509Certificate x509Cert = (X509Certificate) cert;
String thisIssuerName = org.apache.xml.security.utils.RFC2253Parser
.normalize(x509Cert.getIssuerDN().getName());
BigInteger thisSerialNumber = x509Cert.getSerialNumber();
if (thisIssuerName.equals(issuerName)
&& thisSerialNumber.equals(serialNumber)) {
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
}
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}
public PrivateKey getPrivateKey(X509Certificate certificate)
throws IOException {
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
if (!keyStore.isKeyEntry(alias))
continue;
Certificate cert = keyStore.getCertificate(alias);
if (cert != null && cert.equals(certificate))
return (PrivateKey) keyStore.getKey(alias, keyStorePassword
.toCharArray());
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
49 of 67 6/22/2011 2:07 PM
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
return null;
}
private void getDefaultPrivKeyCert(
SignatureKeyCallback.DefaultPrivKeyCertRequest request)
throws IOException {
String uniqueAlias = null;
try {
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String currentAlias = (String) aliases.nextElement();
if (keyStore.isKeyEntry(currentAlias)) {
Certificate thisCertificate = keyStore
.getCertificate(currentAlias);
if (thisCertificate != null) {
if (thisCertificate instanceof X509Certificate) {
if (uniqueAlias == null) {
uniqueAlias = currentAlias;
} else {
// Not unique!
uniqueAlias = null;
break;
}
}
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
50 of 67 6/22/2011 2:07 PM
}
}
if (uniqueAlias != null) {
request.setX509Certificate((X509Certificate) keyStore
.getCertificate(uniqueAlias));
request.setPrivateKey((PrivateKey) keyStore.getKey(uniqueAlias,
keyStorePassword.toCharArray()));
}
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private static byte[] getSubjectKeyIdentifier(X509Certificate cert) {
String SUBJECT_KEY_IDENTIFIER_OID = “2.5.29.14″;
byte[] subjectKeyIdentifier = cert
.getExtensionValue(SUBJECT_KEY_IDENTIFIER_OID);
if (subjectKeyIdentifier == null)
return null;
try {
sun.security.x509.KeyIdentifier keyId = null;
sun.security.util.DerValue derVal = new sun.security.util.DerValue(
new sun.security.util.DerInputStream(subjectKeyIdentifier)
.getOctetString());
keyId = new sun.security.x509.KeyIdentifier(derVal.getOctetString());
return keyId.getIdentifier();
} catch (NoClassDefFoundError ncde) {
if (subjectKeyIdentifier == null)
return null;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
51 of 67 6/22/2011 2:07 PM
byte[] dest = new byte[subjectKeyIdentifier.length - 4];
System.arraycopy(subjectKeyIdentifier, 4, dest, 0,
subjectKeyIdentifier.length – 4);
return dest;
} catch (java.io.IOException ex) {
// ignore
return null;
}
}
private class PlainTextPasswordValidator implements
PasswordValidationCallback.PasswordValidator {
public boolean validate(PasswordValidationCallback.Request request)
throws PasswordValidationCallback.PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest =
(PasswordValidationCallback.PlainTextPasswordRequest) request;
if (“Ron”.equals(plainTextRequest.getUsername())
&& “noR”.equals(plainTextRequest.getPassword())) {
return true;
}
return false;
}
}
private class DefaultTimestampValidator implements
TimestampValidationCallback.TimestampValidator {
public void validate(TimestampValidationCallback.Request request)
throws TimestampValidationCallback.TimestampValidationException {
// validate timestamp creation and expiration time.
TimestampValidationCallback.UTCTimestampRequest utcTimestampRequest =(TimestampValidationCallback.UTCTimestampRequest) request;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
52 of 67 6/22/2011 2:07 PM
SimpleDateFormat calendarFormatter2 = new SimpleDateFormat(
“yyyy-MM-dd’T'HH:mm:ss’Z'”);
SimpleDateFormat calendarFormatter1 = new SimpleDateFormat(
“yyyy-MM-dd’T'HH:mm:ss’.'SSS’Z'”);
Date created = null;
Date expired = null;
try {
try {
created = calendarFormatter1.parse(utcTimestampRequest
.getCreated());
if (utcTimestampRequest.getExpired() != null)
expired = calendarFormatter1.parse(utcTimestampRequest
.getExpired());
} catch (java.text.ParseException pe) {
created = calendarFormatter2.parse(utcTimestampRequest
.getCreated());
if (utcTimestampRequest.getExpired() != null)
expired = calendarFormatter2.parse(utcTimestampRequest
.getExpired());
}
} catch (java.text.ParseException pe) {
throw new TimestampValidationCallback.TimestampValidationException(
pe.getMessage());
}
long maxClockSkew = utcTimestampRequest.getMaxClockSkew();
long timestampFreshnessLimit = utcTimestampRequest
.getTimestampFreshnessLimit();
// validate creation time
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
53 of 67 6/22/2011 2:07 PM
validateCreationTime(created, maxClockSkew, timestampFreshnessLimit);
// validate expiration time
if (expired != null)
validateExpirationTime(expired, maxClockSkew,
timestampFreshnessLimit);
}
}
public void validateExpirationTime(Date expires, long maxClockSkew,
long timestampFreshnessLimit)
throws TimestampValidationCallback.TimestampValidationException {
// System.out.println(“Validate Expiration time called”);
Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),
maxClockSkew, false);
if (expires.before(currentTime)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The current time is ahead of the expiration time in Timestamp”);
}
}
public void validateCreationTime(Date created, long maxClockSkew,
long timestampFreshnessLimit)
throws TimestampValidationCallback.TimestampValidationException {
// System.out.println(“Validate Creation time called”);
Date current = getFreshnessAndSkewAdjustedDate(maxClockSkew,
timestampFreshnessLimit);
if (created.before(current)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The creation time is older than “
+ ” currenttime – timestamp-freshness-limit – max-clock-skew”);
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
54 of 67 6/22/2011 2:07 PM
}
Date currentTime = getGMTDateWithSkewAdjusted(new GregorianCalendar(),
maxClockSkew, true);
if (currentTime.before(created)) {
throw new TimestampValidationCallback.TimestampValidationException(
“The creation time is ahead of the current time.”);
}
}
private static Date getFreshnessAndSkewAdjustedDate(long maxClockSkew,
long timestampFreshnessLimit) {
Calendar c = new GregorianCalendar();
long offset = c.get(Calendar.ZONE_OFFSET);
if (c.getTimeZone().inDaylightTime(c.getTime())) {
offset += c.getTimeZone().getDSTSavings();
}
long beforeTime = c.getTimeInMillis();
long currentTime = beforeTime – offset;
long adjustedTime = currentTime – maxClockSkew
- timestampFreshnessLimit;
c.setTimeInMillis(adjustedTime);
return c.getTime();
}
private static Date getGMTDateWithSkewAdjusted(Calendar c,
long maxClockSkew, boolean addSkew) {
long offset = c.get(Calendar.ZONE_OFFSET);
if (c.getTimeZone().inDaylightTime(c.getTime())) {
offset += c.getTimeZone().getDSTSavings();
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
55 of 67 6/22/2011 2:07 PM
long beforeTime = c.getTimeInMillis();
long currentTime = beforeTime – offset;
if (addSkew)
currentTime = currentTime + maxClockSkew;
else
currentTime = currentTime – maxClockSkew;
c.setTimeInMillis(currentTime);
return c.getTime();
}
private class X509CertificateValidatorImpl implements
CertificateValidationCallback.CertificateValidator {
public boolean validate(X509Certificate certificate)
throws CertificateValidationCallback.CertificateValidationException {
if (isSelfCert(certificate)) {
return true;
}
try {
certificate.checkValidity();
} catch (CertificateExpiredException e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
“X509Certificate Expired”, e);
} catch (CertificateNotYetValidException e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
“X509Certificate not yet valid”, e);
}
X509CertSelector certSelector = new X509CertSelector();
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
56 of 67 6/22/2011 2:07 PM
certSelector.setCertificate(certificate);
PKIXBuilderParameters parameters;
CertPathBuilder builder;
try {
parameters = new PKIXBuilderParameters(trustStore, certSelector);
parameters.setRevocationEnabled(false);
builder = CertPathBuilder.getInstance(“PKIX”);
} catch (Exception e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
e.getMessage(), e);
}
try {
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
.build(parameters);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private boolean isSelfCert(X509Certificate cert)
throws CertificateValidationCallback.CertificateValidationException {
try {
if (keyStore == null)
initKeyStore();
Enumeration aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
57 of 67 6/22/2011 2:07 PM
String alias = (String) aliases.nextElement();
if (keyStore.isKeyEntry(alias)) {
X509Certificate x509Cert = (X509Certificate) keyStore
.getCertificate(alias);
if (x509Cert != null) {
if (x509Cert.equals(cert))
return true;
}
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
throw new CertificateValidationCallback.CertificateValidationException(
e.getMessage(), e);
}
}
}
private String getContainerHome() {
String _home = “”;
String fileSeparator = System.getProperty(“file.separator”);
String contHome = System.getProperty(“catalina.home”);
if (contHome != null) {
String isAS = System.getProperty(“com.sun.aas.instanceRoot”);
if (isAS != null) {
_home = contHome + fileSeparator + “..” + fileSeparator + “..”;
} else {
_home = contHome;
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
58 of 67 6/22/2011 2:07 PM
}
} else {
_home = System.getProperty(“jwsdp.home”);
if (_home == null) {
_home = System.getProperty(“as.home”);
}
}
return _home;
}
}
Step 7: Create the service factory (AuthServiceFactory.java), which is extremely easy since all the work was
done in the Spring file:
package com.sungard.cxf.example.server;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class AuthServiceFactory {
private static final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { “cxfClient.xml” });
public AuthServiceFactory() {
}
public IHello getService() {
return (IHello) context.getBean(“client”);
}
}
Step 8: Create Client.java to invoke the service.
package com.sungard.cxf.example.server;
public final class Client {
private Client() {
}
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
59 of 67 6/22/2011 2:07 PM
public static void main(String args[]) throws Exception {
AuthServiceFactory af = new AuthServiceFactory();
IHello client1 = af.getService();
String response1 = client1.sayHello(“Hello”);
System.out.println(“Response: ” + response1);
}
}
Step 9: Create cxfClient.xml to setup the application context for the client.
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:jaxws=”http://cxf.apache.org/jaxws”
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd”>
<bean id=”proxyFactory”
>
<property name=”serviceClass”
value=”com.sungard.cxf.example.server.IHello” />
<property name=”address”
value=”http://localhost:8080/samlnormalsecurity/HelloService” />
<property name=”inInterceptors”>
<list>
<ref bean=”logIn” />
</list>
</property>
<property name=”outInterceptors”>
<list>
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
60 of 67 6/22/2011 2:07 PM
<ref bean=”logOut” />
<ref bean=”saajOut” />
<ref bean=”wss4jOut” />
</list>
</property>
</bean>
<bean id=”client”
factory-bean=”proxyFactory” factory-method=”create” />
<bean id=”logIn”
/>
<bean id=”logOut”
/>
<bean id=”saajOut”
/>
<bean id=”wss4jOut”
>
<constructor-arg>
<map>
<entry key=”action” value=”UsernameToken SAMLTokenUnsigned” />
<entry key=”user” value=”xws-security-client” />
<entry key=”passwordType” value=”PasswordText” />
<entry key=”samlPropFile” value=”saml2.properties”/>
<entry key=”enableNamespacePrefixOptimization” value=”true”/>
<entry key=”disablePrettyXML” value=”true”/>
<entry key=”sendXsiTypes” value=”true”/>
<entry key=”sendMultiRefs” value=”true”/>
<entry key=”sendXMLDeclaration” value=”true”/>
<entry key=”passwordCallbackClass”
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
61 of 67 6/22/2011 2:07 PM
value=”com.sungard.cxf.example.server.ClientSecurityEnvironmentHandler” />
</map>
</constructor-arg>
</bean>
</beans>
Step 11: Create client_sign.properties file under WEB-INF\classes folder. To give public keystore file details.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.keystore.alias=xws-security-client
org.apache.ws.security.crypto.merlin.file=client-keystore.jks
Step 12: Create saml2.properties file under WEB-INF\classes folder. To give public keystore file details.
org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.SAMLIssuerImpl
org.apache.ws.security.saml.issuer.cryptoProp.file=client_sign.properties
org.apache.ws.security.saml.issuer=www.example.com
org.apache.ws.security.saml.subjectNameId.name=xws-security-client
org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
org.apache.ws.security.saml.authenticationMethod=password
org.apache.ws.security.saml.confirmationMethod=senderVouches
org.apache.ws.security.saml.issuer.key.name=xws-security-client
org.apache.ws.security.saml.issuer.key.password=changeit
Step 13: Copy keystore and certificates in WEB-INF\classes folder. (Or set it in classpath)
Step 14: Run Client.java
You will get response like as follows.
Response: You SaidHello
Note:
Client Side:
We Set User name in client cxfClient.xml file. That is public alias name. (We can set the same through
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
62 of 67 6/22/2011 2:07 PM
program also and we can read it xml/properties files. We can pass the same in runtime also)
<entry key=”user” value=”xws-security-client” />
We Set password in ClientSecurityEnvironmentHandler.java class (We can pass same in runtime also)
// set the password for our message.
pc.setPassword(“changeit”);
You can see the In & Outbound Messages in Client Side. As like as follows. This will go with signature.
INFO: Outbound Message
—————————
Encoding: UTF-8
Headers: {SOAPAction=[""], Accept=[*]}
Messages:
Payload: <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>
<soap:Header>
<wsse:Security xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd” soap:mustUnderstand=”1″><Assertion xmlns=”urn:oasis:names:tc:SAML:1.0:assertion”
xmlns:saml=”urn:oasis:names:tc:SAML:1.0:assertion” xmlns:samlp=”urn:oasis:names:tc:SAML:1.0:protocol”AssertionID=”b58cef8ed07e7a8c1be2d099e73ba075″ IssueInstant=”2008-04-04T05:13:59.068Z”
Issuer=”www.example.com” MajorVersion=”1″ MinorVersion=”1″><AuthenticationStatement
AuthenticationInstant=”2008-04-04T05:13:58.896Z”AuthenticationMethod=”urn:oasis:names:tc:SAML:1.0:am:password”><Subject><NameIdentifier
NameQualifier=”www.example.com”>xws-security-client</NameIdentifier><SubjectConfirmation>
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</ConfirmationMethod></SubjectConfirmation></Subject></AuthenticationStatement></Assertion><wsse:UsernameToken
xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”
wsu:Id=”UsernameToken-24451742″ xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”><wsse:Username xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-
200401-wss-wssecurity-secext-1.0.xsd”>xws-security-client</wsse:Username><wsse:Password
Type=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText”xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-
1.0.xsd”>changeit</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body>
<ns1:sayHello xmlns:ns1=”http://server.example.cxf.sungard.com/”><arg0>Hello</arg0></ns1:sayHello></soap:Body></soap:Envelope>
————————————–
Apr 4, 2008 10:44:10 AM org.apache.cxf.interceptor.LoggingInInterceptor logging
INFO: Inbound Message
—————————-
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
63 of 67 6/22/2011 2:07 PM
Share this: Facebook Print Email
Like Be the first to like this post.
Encoding: UTF-8
Headers: {Content-Length=[230], Date=[Fri, 04 Apr 2008 05:14:10 GMT], SOAPAction=[""], Server=
[Apache-Coyote/1.1], content-type=[text/xml;charset=UTF-8]}
Messages:
Message:
Payload: <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”><soap:Body>
<ns1:sayHelloResponse xmlns:ns1=”http://server.example.cxf.sungard.com/”><return>YouSaidHello</return></ns1:sayHelloResponse></soap:Body></soap:Envelope>
————————————–
September 4, 2009 - Posted by Peter Arockiaraj | Web Services
2 Comments »
Hi Peter,
Excellent Article, good work….
Can u able to share the working source code for me ?…….
Thanks & Regards,
Ibrahim
Comment by Ibrahim | November 26, 2010 | Reply
1.
Hi Peter,2.
Ads by Google
Download Google
Chrome
Searching is fast and easy with Google'sweb browser.
www.Google.com/Chrome
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
64 of 67 6/22/2011 2:07 PM
Notify me of follow-up comments via email.
Notify me of new posts via email.
Post Comment
Good Article!!
Can you send me the source code?
Regards,
Gerard
Comment by Gerard | March 11, 2011 | Reply
Leave a Reply
« Previous | Next »
About Me
Log In Log In Log In
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
65 of 67 6/22/2011 2:07 PM
Share this: Facebook Print Email
Peter has over 8 years of experience & has worked in several roles. Working
in Professional services Team in SunGard Technology Services. He is Technical Consultant in customization
team.
He started his career in SoftTech Ltd & as Software Engineer. And worked in leading software organizations
like GoRemote/iPass, Satyam and now in Sungard.
He holds a Master degree in Science from Madurai Kamaraj University.
More details about Peter can be viewed at http://www.linkedin.com/in/peterarockiaraj. Peter is currently in
India and can be reached on his email at [email protected].
Recent
Integrating JSF, Spring Security and LDAP
Developing Web Services by using Mule, CXF, and SpringDeveloping Web Services by Using Metro Webservices Framework
Developing CXF WS-Security with Spring & Acegi Security
Developing CXF WS-Security with SAMLDeveloping CXF WS-Security with Signature(Certificates)
Developing CXF Web services with WS-Security
RESTful web services using the Jersey frameworkDeveloping Web Services By Using Spring and CXF
Developing Web Services by Using Spring and XFire
Developing Web services Using Spring FrameworkDeveloping Simple Web Services by Using JWSDP
Links
WordPress.com
WordPress.org
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
66 of 67 6/22/2011 2:07 PM
Archives
January 2010 (1)
November 2009 (1)
October 2009 (1)September 2009 (9)
Categories
Java
Web Services
RSS
Entries RSS
Comments RSS
Site info
Peter Arockiaraj
Theme: Andreas04 by Andreas Viklund. Blog at WordPress.com.
Developing CXF WS-Security with SAML « Peter Arockiaraj http://peterarockiaraj.wordpress.com/2009/09/04/developing-cxf-ws-secu...
67 of 67 6/22/2011 2:07 PM