Developing CXF WS-Security with SAML
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)- Optional
- CXF Jars (Required for Compilation-Download from http://cxf.apache.org/download.html)
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)
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
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 named client.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 ssl
and 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
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
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 output folder 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 you have 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”;
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;
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++) {
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];
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
.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) {
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) {
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) {
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
.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 {
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 {
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;
}
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) {
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”);
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());
}
} 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;
}
}
}
}
}
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(
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 = (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 {
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”);
}
}
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”);
}
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);
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
.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(
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);
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 + “..”;
} 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);
}
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
.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
.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”>
<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
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>
</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.
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;
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;
/**
* 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();
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
.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) {
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();
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
.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;
}
}
}
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();
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);
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;
}
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;
}
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());
}
} 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;
}
}
}
}
}
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;
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;
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
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”);
}
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();
}
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();
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()) {
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;
}
} 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() {
}
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>
<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”
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 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
—————————-
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>You SaidHello</return></ns1:sayHelloResponse></soap:Body></soap:Envelope>
————————————–
5 Comments »
Leave a comment
-
Recent
- Integrating JSF, Spring Security and LDAP
- Developing Web Services by using Mule, CXF, and Spring
- Developing Web Services by Using Metro Webservices Framework
- Developing CXF WS-Security with Spring & Acegi Security
- Developing CXF WS-Security with SAML
- Developing CXF WS-Security with Signature(Certificates)
- Developing CXF Web services with WS-Security
- RESTful web services using the Jersey framework
- Developing Web Services By Using Spring and CXF
- Developing Web Services by Using Spring and XFire
- Developing Web services Using Spring Framework
- Developing Simple Web Services by Using JWSDP
-
Links
-
Archives
- January 2010 (1)
- November 2009 (1)
- October 2009 (1)
- September 2009 (9)
-
Categories
-
RSS
Entries RSS
Comments RSS
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 |
Hi Peter,
Good Article!!
Can you send me the source code?
Regards,
Gerard
Comment by Gerard | March 11, 2011 |
Dude I got this finally working the links that were helpful to me was not your blog actually but the following :
http://coheigea.blogspot.com/2011/04/saml-support-in-cxf-240.html
if you plan on providing any code in future please consider releasing it in the form of Jar or a war or a zip file at a location it could save grey hair for many
Comment by Naga | May 9, 2011 |
it’s impossible to read this post. can you format the code, please?
Comment by andrej | August 24, 2011 |
thanks for creating a blog on this…. consider using a code formatter to help your blog readers and a link to the repo…
Comment by Balaji Krishnan | July 13, 2014 |