diff --git a/security/src/main/java/org/springframework/ws/soap/security/callback/CallbackHandlerChain.java b/security/src/main/java/org/springframework/ws/soap/security/callback/CallbackHandlerChain.java
new file mode 100644
index 00000000..affbc0b5
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/callback/CallbackHandlerChain.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.callback;
+
+import java.io.IOException;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * Represents a chain of CallbackHandlers. For each callback, each of the handlers is called in term. If a
+ * handler throws a UnsupportedCallbackException, the next handler is tried.
+ *
+ * @author Arjen Poutsma
+ * @since 1.5.0
+ */
+public class CallbackHandlerChain extends AbstractCallbackHandler {
+
+ private final CallbackHandler[] callbackHandlers;
+
+ public CallbackHandlerChain(CallbackHandler[] callbackHandlers) {
+ this.callbackHandlers = callbackHandlers;
+ }
+
+ public CallbackHandler[] getCallbackHandlers() {
+ return callbackHandlers;
+ }
+
+ protected void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException {
+ boolean allUnsupported = true;
+ for (int i = 0; i < callbackHandlers.length; i++) {
+ CallbackHandler callbackHandler = callbackHandlers[i];
+ try {
+ callbackHandler.handle(new Callback[]{callback});
+ allUnsupported = false;
+ }
+ catch (UnsupportedCallbackException ex) {
+ // if an UnsupportedCallbackException occurs, go to the next handler
+ }
+ }
+ if (allUnsupported) {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+}
\ No newline at end of file
diff --git a/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java
index f452206a..8f430ba5 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreFactoryBean.java
@@ -87,7 +87,7 @@ public class KeyStoreFactoryBean implements FactoryBean, InitializingBean {
this.type = type;
}
- public Object getObject() throws Exception {
+ public Object getObject() {
return keyStore;
}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java
new file mode 100644
index 00000000..81e124c3
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.support;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.util.StringUtils;
+
+/**
+ * Generic utility methods for dealing with {@link KeyStore} objects.
+ *
+ * @author Arjen Poutsma
+ * @since 1.5.0
+ */
+public abstract class KeyStoreUtils {
+
+ /**
+ * Loads the key store indicated by system properties. This method tries to load a key store by consulting the
+ * following system properties:javax.net.ssl.keyStore, javax.net.ssl.keyStorePassword, and
+ * javax.net.ssl.keyStoreType.
+ *
+ * If these properties specify a file with an appropriate password, the factory uses this file for the key store. If
+ * that file does not exist, then a default, empty keystore is created.
+ *
+ * This behavior corresponds to the standard J2SDK behavior for SSL key stores.
+ *
+ * @see The
+ * standard J2SDK SSL key store mechanism
+ */
+ public static KeyStore loadDefaultKeyStore() throws GeneralSecurityException, IOException {
+ Resource location = null;
+ String type = null;
+ String password = null;
+ String locationProperty = System.getProperty("javax.net.ssl.keyStore");
+ if (StringUtils.hasLength(locationProperty)) {
+ File f = new File(locationProperty);
+ if (f.exists() && f.isFile() && f.canRead()) {
+ location = new FileSystemResource(f);
+ }
+ String passwordProperty = System.getProperty("javax.net.ssl.keyStorePassword");
+ if (StringUtils.hasLength(passwordProperty)) {
+ password = passwordProperty;
+ }
+ type = System.getProperty("javax.net.ssl.trustStore");
+ }
+ // use the factory bean here, easier to setup
+ KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();
+ factoryBean.setLocation(location);
+ factoryBean.setPassword(password);
+ factoryBean.setType(type);
+ factoryBean.afterPropertiesSet();
+ return (KeyStore) factoryBean.getObject();
+ }
+
+ /**
+ * Loads a default trust store. This method uses the following algorithm: - If the system property
+ *
javax.net.ssl.trustStore is defined, its value is loaded. If the
+ * javax.net.ssl.trustStorePassword system property is also defined, its value is used as a password.
+ * If the javax.net.ssl.trustStoreType system property is defined, its value is used as a key store
+ * type.
+ *
+ * If javax.net.ssl.trustStore is defined but the specified file does not exist, then a default, empty
+ * trust store is created. - If the
javax.net.ssl.trustStore system property was not
+ * specified, but if the file $JAVA_HOME/lib/security/jssecacerts exists, that file is used.
+ * Otherwise, - If the file
$JAVA_HOME/lib/security/cacerts exists, that file is used.
+ *
+ * This behavior corresponds to the standard J2SDK behavior for SSL trust stores.
+ *
+ * @see The
+ * standard J2SDK SSL trust store mechanism
+ */
+ public static KeyStore loadDefaultTrustStore() throws GeneralSecurityException, IOException {
+ Resource location = null;
+ String type = null;
+ String password = null;
+ String locationProperty = System.getProperty("javax.net.ssl.trustStore");
+ if (StringUtils.hasLength(locationProperty)) {
+ File f = new File(locationProperty);
+ if (f.exists() && f.isFile() && f.canRead()) {
+ location = new FileSystemResource(f);
+ }
+ String passwordProperty = System.getProperty("javax.net.ssl.trustStorePassword");
+ if (StringUtils.hasLength(passwordProperty)) {
+ password = passwordProperty;
+ }
+ type = System.getProperty("javax.net.ssl.trustStoreType");
+ }
+ else {
+ String javaHome = System.getProperty("java.home");
+ location = new FileSystemResource(javaHome + "/lib/security/jssecacerts");
+ if (!location.exists()) {
+ location = new FileSystemResource(javaHome + "/lib/security/cacerts");
+ }
+ }
+ // use the factory bean here, easier to setup
+ KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();
+ factoryBean.setLocation(location);
+ factoryBean.setPassword(password);
+ factoryBean.setType(type);
+ factoryBean.afterPropertiesSet();
+ return (KeyStore) factoryBean.getObject();
+ }
+
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java
index fb0ce53a..4815688f 100755
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java
@@ -46,39 +46,31 @@ import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor;
import org.springframework.ws.soap.security.WsSecuritySecurementException;
import org.springframework.ws.soap.security.WsSecurityValidationException;
+import org.springframework.ws.soap.security.callback.CallbackHandlerChain;
/**
* A WS-Security endpoint interceptor based on Apache's WSS4J. This inteceptor supports messages created by the {@link
* org.springframework.ws.soap.axiom.AxiomSoapMessageFactory} and the {@link org.springframework.ws.soap.saaj.SaajSoapMessageFactory}.
*
- * The validation and securement actions executed by this interceptor are configured via validationActions and
- * securementActions properties, respectively. Actions should be passed as a space-separated strings.
+ * The validation and securement actions executed by this interceptor are configured via validationActions
+ * and securementActions properties, respectively. Actions should be passed as a space-separated strings.
*
* Valid validation actions are:
- *
- *
- * | Validation action | Description |
- * UsernameToken | Validates username token |
- * Timestamp | Validates the timestamp |
- * Encrypt | Decrypts the message |
- * Signature | Validates the signature |
- * NoSecurity | No action performed |
- *
*
- * Securement actions are:
- *
- * | Securement action | Description |
- * UsernameToken | Adds a username token |
- * UsernameTokenSignature | Adds a username token and a signature username token secrect key |
- * Timestamp | Adds a timestamp |
- * Encrypt | Encrypts the response |
- * Signature | Signs the response |
- * NoSecurity | No action performed |
- *
+ * | Validation action | Description |
UsernameToken | Validates
+ * username token |
Timestamp | Validates the timestamp |
+ * Encrypt | Decrypts the message |
Signature | Validates
+ * the signature |
NoSecurity | No action performed |
*
- * The order of the actions that the client performed to secure the messages is significant and is
- * enforced by the interceptor.
- *
+ * Securement actions are: | Securement action | Description |
+ * UsernameToken | Adds a username token |
UsernameTokenSignature | Adds
+ * a username token and a signature username token secrect key |
Timestamp | Adds a
+ * timestamp |
Encrypt | Encrypts the response |
+ * Signature | Signs the response |
NoSecurity | No action
+ * performed |
+ *
+ * The order of the actions that the client performed to secure the messages is significant and is enforced by the
+ * interceptor.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
@@ -89,8 +81,6 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
public static final String SECUREMENT_USER_PROPERTY_NAME = "Wss4jSecurityInterceptor.securementUser";
- private CallbackHandler validationCallbackHandler;
-
private int securementAction;
private String securementActions;
@@ -99,9 +89,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
private String securementUsername;
- private boolean timestampStrict = true;
-
- private int timeToLive = 300;
+ private CallbackHandler validationCallbackHandler;
private int validationAction;
@@ -115,10 +103,14 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
private Crypto validationSignatureCrypto;
- private Wss4jHandler handler = new Wss4jHandler();
+ private boolean timestampStrict = true;
private boolean enableSignatureConfirmation;
+ private int timeToLive = 300;
+
+ private Wss4jHandler handler = new Wss4jHandler();
+
public void setSecurementActions(String securementActions) {
this.securementActions = securementActions;
securementActionsVector = new Vector();
@@ -141,10 +133,24 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
handler.setOption(WSHandlerConstants.ACTOR, securementActor);
}
+ /**
+ * Sets the {@link org.apache.ws.security.WSPasswordCallback} handler to use when securing messages.
+ *
+ * @see #setSecurementCallbackHandlers(CallbackHandler[])
+ */
public void setSecurementCallbackHandler(CallbackHandler securementCallbackHandler) {
handler.setSecurementCallbackHandler(securementCallbackHandler);
}
+ /**
+ * Sets the {@link org.apache.ws.security.WSPasswordCallback} handlers to use when securing messages.
+ *
+ * @see #setSecurementCallbackHandler(CallbackHandler)
+ */
+ public void setSecurementCallbackHandlers(CallbackHandler[] securementCallbackHandler) {
+ handler.setSecurementCallbackHandler(new CallbackHandlerChain(securementCallbackHandler));
+ }
+
public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) {
handler.setSecurementEncryptionCrypto(securementEncryptionCrypto);
}
@@ -333,10 +339,24 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
this.validationActor = validationActor;
}
+ /**
+ * Sets the {@link org.apache.ws.security.WSPasswordCallback} handler to use when validating messages.
+ *
+ * @see #setValidationCallbackHandlers(CallbackHandler[])
+ */
public void setValidationCallbackHandler(CallbackHandler callbackHandler) {
this.validationCallbackHandler = callbackHandler;
}
+ /**
+ * Sets the {@link org.apache.ws.security.WSPasswordCallback} handlers to use when validating messages.
+ *
+ * @see #setValidationCallbackHandler(CallbackHandler)
+ */
+ public void setValidationCallbackHandlers(CallbackHandler[] callbackHandler) {
+ this.validationCallbackHandler = new CallbackHandlerChain(callbackHandler);
+ }
+
/** Sets the Crypto to use to decrypt incoming messages */
public void setValidationDecryptionCrypto(Crypto decryptionCrypto) {
this.validationDecryptionCrypto = decryptionCrypto;
@@ -410,6 +430,9 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
if (securementAction == WSConstants.NO_SECURITY && !enableSignatureConfirmation) {
return;
}
+ if (logger.isDebugEnabled()) {
+ logger.debug("Securing message [" + soapMessage + "] with actions [" + securementActions + "]");
+ }
RequestData requestData = initializeRequestData(messageContext);
Document envelopeAsDocument = toDocument(soapMessage);
@@ -450,7 +473,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecurityValidationException {
if (logger.isDebugEnabled()) {
- logger.debug("Validating message [" + soapMessage + "] with actions " + validationActions);
+ logger.debug("Validating message [" + soapMessage + "] with actions [" + validationActions + "]");
}
if (validationAction == WSConstants.NO_SECURITY) {
@@ -508,11 +531,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl
messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults);
}
- /**
- * Verifies the trust of a certificate.
- * @param results
- * @throws WSSecurityException
- */
+ /** Verifies the trust of a certificate. */
protected void verifyCertificateTrust(Vector results) throws WSSecurityException {
RequestData requestData = new RequestData();
requestData.setSigCrypto(validationSignatureCrypto);
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java
new file mode 100644
index 00000000..9e1f7423
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback;
+
+import java.io.IOException;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.ws.security.WSPasswordCallback;
+
+import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
+
+/**
+ * Abstract base class for {@link javax.security.auth.callback.CallbackHandler} implementations that handle {@link
+ * WSPasswordCallback} callbacks.
+ *
+ * @author Arjen Poutsma
+ * @since 1.5.0
+ */
+public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallbackHandler {
+
+ /**
+ * Handles {@link WSPasswordCallback} callbacks. Inspects the callback {@link WSPasswordCallback#getUsage() usage}
+ * code, and calls the various handle* template methods.
+ *
+ * @param callback the callback
+ * @throws IOException in case of I/O errors
+ * @throws UnsupportedCallbackException when the callback is not supported
+ */
+ protected final void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException {
+ if (callback instanceof WSPasswordCallback) {
+ WSPasswordCallback passwordCallback = (WSPasswordCallback) callback;
+ switch (passwordCallback.getUsage()) {
+ case WSPasswordCallback.DECRYPT:
+ handleDecrypt(passwordCallback);
+ break;
+ case WSPasswordCallback.USERNAME_TOKEN:
+ handleUsernameToken(passwordCallback);
+ break;
+ case WSPasswordCallback.SIGNATURE:
+ handleSignature(passwordCallback);
+ break;
+ case WSPasswordCallback.KEY_NAME:
+ handleKeyName(passwordCallback);
+ break;
+ case WSPasswordCallback.USERNAME_TOKEN_UNKNOWN:
+ handleUsernameTokenUnknown(passwordCallback);
+ break;
+ case WSPasswordCallback.SECURITY_CONTEXT_TOKEN:
+ handleSecurityContextToken(passwordCallback);
+ break;
+ case WSPasswordCallback.CUSTOM_TOKEN:
+ handleCustomToken(passwordCallback);
+ break;
+ case WSPasswordCallback.ENCRYPTED_KEY_TOKEN:
+ handleEncryptedKeyToken(callback);
+ break;
+ default:
+ throw new UnsupportedCallbackException(callback,
+ "Unknown usage [" + passwordCallback.getUsage() + "]");
+ }
+ }
+ else {
+ throw new UnsupportedCallbackException(callback);
+ }
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#DECRYPT} usage.
+ *
+ * This method is invoked when WSS4J needs a password to get the private key of the {@link
+ * WSPasswordCallback#getIdentifer() identifier} (username) from the keystore. WSS4J uses this private key to
+ * decrypt the session (symmetric) key. Because the encryption method uses the public key to encrypt the session key
+ * it needs no password (a public key is usually not protected by a password).
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleDecrypt(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#USERNAME_TOKEN} usage.
+ *
+ * This method is invoked when WSS4J needs the password to fill in or to verify a UsernameToken.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#SIGNATURE} usage.
+ *
+ * This method is invoked when WSS4J needs the password to get the private key of the {@link
+ * WSPasswordCallback#getIdentifer() identifier} (username) from the keystore. WSS4J uses this private key to
+ * produce a signature. The signature verfication uses the public key to verfiy the signature.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleSignature(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#KEY_NAME} usage.
+ *
+ * This method is invoked when WSS4J needs the key associated with the {@link WSPasswordCallback#getIdentifer()
+ * identifier}. WSS4J uses this key to encrypt or decrypt parts of the SOAP request. Note, the key must match the
+ * symmetric encryption/decryption algorithm specified (refer to {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_SYM_ALGO}).
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleKeyName(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#USERNAME_TOKEN_UNKNOWN} usage.
+ *
+ * This method is invoked for a not specified password type or a plain text password type. Only the {@link
+ * WSPasswordCallback#getPassword() password} is set. The callback class now may check if the username and password
+ * match. If they don't match, the subclass should throw an exception.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleUsernameTokenUnknown(WSPasswordCallback callback)
+ throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#SECURITY_CONTEXT_TOKEN} usage.
+ *
+ * This method is invoked when WSS4J needs the key to to be associated with a SecurityContextToken.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleSecurityContextToken(WSPasswordCallback callback)
+ throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#CUSTOM_TOKEN} usage.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleCustomToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ /**
+ * Invoked when the callback has a {@link WSPasswordCallback#ENCRYPTED_KEY_TOKEN} usage.
+ *
+ * Default implementation throws an {@link UnsupportedCallbackException}.
+ */
+ protected void handleEncryptedKeyToken(Callback callback) throws IOException, UnsupportedCallbackException {
+ throw new UnsupportedCallbackException(callback);
+ }
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWss4jCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWss4jCallbackHandler.java
deleted file mode 100755
index 6f3869f3..00000000
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWss4jCallbackHandler.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2006 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.ws.soap.security.wss4j.callback;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStore.Entry;
-import javax.crypto.SecretKey;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.apache.ws.security.WSPasswordCallback;
-import org.apache.ws.security.WSSecurityException;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.util.Assert;
-import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
-
-/**
- * A base class for callback handlers.
- *
- * @author Tareq Abed Rabbo
- */
-public abstract class AbstractWss4jCallbackHandler extends AbstractCallbackHandler implements InitializingBean {
-
- private boolean passwordDigestRequired;
-
- private boolean passwordPlainTextRequired;
-
- private String keyPassword;
-
- private KeyStore keyStore;
-
- /** Sets the key store to use if a symmetric key name is embedded. */
- public void setKeyStore(KeyStore keyStore) {
- this.keyStore = keyStore;
- }
-
- /** Sets if a digest password is required. */
- public void setPasswordDigestRequired(boolean passwordDigestRequired) {
- this.passwordDigestRequired = passwordDigestRequired;
- }
-
- /** Sets the password of the key used for decryption. */
- public void setKeyPassword(String keyPassword) {
- this.keyPassword = keyPassword;
- }
-
- /** Sets if a plain text password is required. */
- public void setPasswordPlainTextRequired(boolean passwordPlainTextRequired) {
- this.passwordPlainTextRequired = passwordPlainTextRequired;
- }
-
- /** Returns the password of the key used for decryption. */
- public String getKeyPassword() {
- return keyPassword;
- }
-
- /** Returns if a digest password is required. */
- public boolean isPasswordDigestRequired() {
- return passwordDigestRequired;
- }
-
- /** Returns if a plain text password is required. */
- public boolean isPasswordPlainTextRequired() {
- return passwordPlainTextRequired;
- }
-
- /** Gets the key store to use if a symmetric key name is embedded. */
- public KeyStore getKeyStore() {
- return keyStore;
- }
-
- public void afterPropertiesSet() throws Exception {
- Assert
- .isTrue(!(passwordDigestRequired && passwordPlainTextRequired),
- "passwordDigestRequired and passwordPlainTextRequired can not be true in the same time");
- }
-
- protected final void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException {
-
- if (callback instanceof WSPasswordCallback) {
- WSPasswordCallback passwordCallback = (WSPasswordCallback) callback;
-
- int usage = passwordCallback.getUsage();
-
- if (passwordDigestRequired && !(usage == WSPasswordCallback.USERNAME_TOKEN)) {
- throw new WSSecurityException("digest password required");
- }
-
- if (passwordPlainTextRequired && !(usage == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN)) {
- throw new WSSecurityException("plain text password required");
- }
-
- String id = passwordCallback.getIdentifer();
- switch (usage) {
-
- // plain text password
- case WSPasswordCallback.USERNAME_TOKEN_UNKNOWN:
- validateUsernameTokenPlainText(passwordCallback);
- return;
-
- // digest password
- case WSPasswordCallback.USERNAME_TOKEN:
- validateUsernameTokenDigest(passwordCallback);
- return;
-
- // decryption
- case WSPasswordCallback.DECRYPT:
- passwordCallback.setPassword(getDecryptionKeyPassword(id));
- return;
-
- // decryption with an embedded symmetric key name
- case WSPasswordCallback.KEY_NAME:
- try {
- KeyStore.PasswordProtection protection =
- new KeyStore.PasswordProtection(getSymmetricKeyPassword(id).toCharArray());
- Entry entry = keyStore.getEntry(id, protection);
- if (entry instanceof KeyStore.SecretKeyEntry) {
- KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) entry;
- SecretKey secretKey = secretKeyEntry.getSecretKey();
- passwordCallback.setKey(secretKey.getEncoded());
- }
- else {
- throw new RuntimeException("key must be instance of javax.crypto.SecretKey:" + id);
- }
- }
- catch (GeneralSecurityException ex) {
- throw new Wss4jSecurityCallbackHandlerException(ex
- .getMessage(), ex);
- }
- return;
- default:
- throw new UnsupportedOperationException("usage type not suporrted:" + usage);
- }
- }
- else {
- throw new UnsupportedCallbackException(callback);
- }
- }
-
- protected String getDecryptionKeyPassword(String id) {
- return keyPassword;
- }
-
- protected String getSymmetricKeyPassword(String id) {
- return keyPassword;
- }
-
- /**
- * validates a Username token with a plain text password. The implementation must validate the username and the
- * password and must throw an exception if the token is not valid
- *
- * @param callback the callback created by Wss4j
- * @throws WSSecurityException if the token is not valid
- */
- abstract protected void validateUsernameTokenPlainText(WSPasswordCallback callback) throws WSSecurityException;
-
- /**
- * validates a Username token with a digest password. The implementation must fetch the clear password of the and
- * set the password attribute of the callback. Wss4j performs the validation logic.
- *
- * @param callback the callback created by Wss4j
- * @throws WSSecurityException if the token is not valid
- */
- abstract protected void validateUsernameTokenDigest(WSPasswordCallback callback) throws WSSecurityException;
-}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java
new file mode 100644
index 00000000..f57850fa
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.ws.soap.security.support.KeyStoreUtils;
+
+/**
+ * Callback handler that uses Java Security KeyStores to handle cryptographic callbacks. Allows for
+ * specific key stores to be set for various cryptographic operations.
+ *
+ * @author Tareq Abed Rabbo
+ * @author Arjen Poutsma
+ * @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
+ * @since 1.5.0
+ */
+public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler implements InitializingBean {
+
+ private String privateKeyPassword;
+
+ private char[] symmetricKeyPassword;
+
+ private KeyStore keyStore;
+
+ /** Sets the key store to use if a symmetric key name is embedded. */
+ public void setKeyStore(KeyStore keyStore) {
+ this.keyStore = keyStore;
+ }
+
+ /**
+ * Sets the password used to retrieve private keys from the keystore. This property is required for decription based
+ * on private keys, and signing.
+ */
+ public void setPrivateKeyPassword(String privateKeyPassword) {
+ if (privateKeyPassword != null) {
+ this.privateKeyPassword = privateKeyPassword;
+ }
+ }
+
+ /**
+ * Sets the password used to retrieve keys from the symmetric keystore. If this property is not set, it default to
+ * the private key password.
+ *
+ * @see #setPrivateKeyPassword(String)
+ */
+ public void setSymmetricKeyPassword(String symmetricKeyPassword) {
+ if (symmetricKeyPassword != null) {
+ this.symmetricKeyPassword = symmetricKeyPassword.toCharArray();
+ }
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (keyStore == null) {
+ loadDefaultKeyStore();
+ }
+ if (symmetricKeyPassword == null) {
+ symmetricKeyPassword = privateKeyPassword.toCharArray();
+ }
+ }
+
+ protected void handleDecrypt(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ callback.setPassword(privateKeyPassword);
+ }
+
+ protected void handleKeyName(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ try {
+ String identifier = callback.getIdentifer();
+ KeyStore.PasswordProtection protection = new KeyStore.PasswordProtection(symmetricKeyPassword);
+ KeyStore.Entry entry = keyStore.getEntry(identifier, protection);
+ if (entry instanceof KeyStore.SecretKeyEntry) {
+ KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) entry;
+ SecretKey secretKey = secretKeyEntry.getSecretKey();
+ callback.setKey(secretKey.getEncoded());
+ }
+ else {
+ throw new WSSecurityException("Key entry [" + entry + "] is not a javax.crypto.SecretKey");
+ }
+ }
+ catch (GeneralSecurityException ex) {
+ throw new WSSecurityException("Could not obtain symmetric key", ex);
+ }
+ }
+
+ /** Loads the key store indicated by system properties. Delegates to {@link KeyStoreUtils#loadDefaultKeyStore()}. */
+ protected void loadDefaultKeyStore() {
+ try {
+ keyStore = KeyStoreUtils.loadDefaultKeyStore();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Loaded default key store");
+ }
+ }
+ catch (Exception ex) {
+ logger.warn("Could not open default key store", ex);
+ }
+ }
+
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimpleCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimpleCallbackHandler.java
deleted file mode 100755
index f9c5e63b..00000000
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimpleCallbackHandler.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2006 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.ws.soap.security.wss4j.callback;
-
-import java.util.Properties;
-
-import org.apache.ws.security.WSPasswordCallback;
-import org.apache.ws.security.WSSecurityException;
-
-/** @author Tareq Abed Rabbo */
-public class SimpleCallbackHandler extends AbstractWss4jCallbackHandler {
-
- private Properties users = new Properties();
-
- public void setUsers(Properties users) {
- this.users = users;
- }
-
- public Properties getUsers() {
- return users;
- }
-
- protected void validateUsernameTokenPlainText(WSPasswordCallback callback) throws WSSecurityException {
- String storedPassword = users.getProperty(callback.getIdentifer());
- if (!(storedPassword != null && storedPassword.equals(callback
- .getPassword()))) {
- throw new WSSecurityException(WSSecurityException.FAILURE);
- }
- }
-
- protected void validateUsernameTokenDigest(WSPasswordCallback callback) throws WSSecurityException {
- callback.setPassword(users.getProperty((callback.getIdentifer())));
- }
-}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/Wss4jSecurityCallbackHandlerException.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordCallbackHandler.java
old mode 100755
new mode 100644
similarity index 59%
rename from security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/Wss4jSecurityCallbackHandlerException.java
rename to security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordCallbackHandler.java
index a7b2cc72..730c27f3
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/Wss4jSecurityCallbackHandlerException.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordCallbackHandler.java
@@ -1,31 +1,25 @@
-/*
- * Copyright 2006 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.ws.soap.security.wss4j.callback;
-
-import org.springframework.ws.soap.security.WsSecurityException;
-
-public class Wss4jSecurityCallbackHandlerException extends WsSecurityException {
-
- public Wss4jSecurityCallbackHandlerException(String msg, Throwable ex) {
- super(msg, ex);
- }
-
- public Wss4jSecurityCallbackHandlerException(String msg) {
- super(msg);
- }
-
-}
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback;
+
+/**
+ * @author Arjen Poutsma
+ * @since 1.5.0
+ */
+public class SimplePasswordCallbackHandler {
+
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java
new file mode 100644
index 00000000..d2cc5d89
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.Assert;
+
+/**
+ * Simple callback handler that validates passwords agains a in-memory Properties object. Password
+ * validation is done on a case-sensitive basis.
+ *
+ * @author Tareq Abed Rabbo
+ * @author Arjen Poutsma
+ * @see #setUsers(java.util.Properties)
+ * @since 1.5.0
+ */
+public class SimplePasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler
+ implements InitializingBean {
+
+ private Properties users = new Properties();
+
+ /** Sets the users to validate against. Property names are usernames, property values are passwords. */
+ public void setUsers(Properties users) {
+ this.users = users;
+ }
+
+ public void setUsersMap(Map users) {
+ for (Iterator iterator = users.keySet().iterator(); iterator.hasNext();) {
+ String username = (String) iterator.next();
+ String password = (String) users.get(username);
+ this.users.setProperty(username, password);
+ }
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(users, "users is required");
+ }
+
+ protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ String identifier = callback.getIdentifer();
+ callback.setPassword(users.getProperty(identifier));
+ }
+
+ protected void handleUsernameTokenUnknown(WSPasswordCallback callback)
+ throws IOException, UnsupportedCallbackException {
+ String identifier = callback.getIdentifer();
+ String storedPassword = users.getProperty(identifier);
+ String givenPassword = callback.getPassword();
+ if (storedPassword == null || !storedPassword.equals(givenPassword)) {
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
new file mode 100644
index 00000000..5cb34b55
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback.acegi;
+
+import java.io.IOException;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.acegisecurity.providers.dao.UserCache;
+import org.acegisecurity.providers.dao.cache.NullUserCache;
+import org.acegisecurity.userdetails.UserDetails;
+import org.acegisecurity.userdetails.UserDetailsService;
+import org.acegisecurity.userdetails.UsernameNotFoundException;
+import org.apache.ws.security.WSPasswordCallback;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.util.Assert;
+import org.springframework.ws.soap.security.wss4j.callback.AbstractWsPasswordCallbackHandler;
+
+/**
+ * Callback handler that validates a password digest using an Acegi UserDetailsService. Logic based on
+ * Acegi's DigestProcessingFilter.
+ *
+ * An Acegi UserDetailService is used to load UserDetails from. The digest of the password
+ * contained in this details object is then compared with the digest in the message.
+ *
+ * @author Arjen Poutsma
+ * @see org.acegisecurity.userdetails.UserDetailsService
+ * @see org.acegisecurity.ui.digestauth.DigestProcessingFilter
+ * @since 1.0.0
+ */
+public class AcegiDigestPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler {
+
+ private UserCache userCache = new NullUserCache();
+
+ private UserDetailsService userDetailsService;
+
+ /** Sets the users cache. Not required, but can benefit performance. */
+ public void setUserCache(UserCache userCache) {
+ this.userCache = userCache;
+ }
+
+ /** Sets the Acegi user details service. Required. */
+ public void setUserDetailsService(UserDetailsService userDetailsService) {
+ this.userDetailsService = userDetailsService;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(userDetailsService, "userDetailsService is required");
+ }
+
+ protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
+ String identifier = callback.getIdentifer();
+ UserDetails user = loadUserDetails(identifier);
+ if (user != null) {
+ callback.setPassword(user.getPassword());
+ }
+ }
+
+ private UserDetails loadUserDetails(String username) throws DataAccessException {
+ UserDetails user = userCache.getUserFromCache(username);
+
+ if (user == null) {
+ try {
+ user = userDetailsService.loadUserByUsername(username);
+ }
+ catch (UsernameNotFoundException notFound) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Username '" + username + "' not found");
+ }
+ return null;
+ }
+ userCache.putUserInCache(user);
+ }
+ return user;
+ }
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiPlainTextPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiPlainTextPasswordValidationCallbackHandler.java
new file mode 100644
index 00000000..cbce2e1e
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiPlainTextPasswordValidationCallbackHandler.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ws.soap.security.wss4j.callback.acegi;
+
+import java.io.IOException;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.acegisecurity.Authentication;
+import org.acegisecurity.AuthenticationException;
+import org.acegisecurity.AuthenticationManager;
+import org.acegisecurity.context.SecurityContextHolder;
+import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+
+import org.springframework.util.Assert;
+import org.springframework.ws.soap.security.wss4j.callback.AbstractWsPasswordCallbackHandler;
+
+/**
+ * Callback handler that validates a certificate uses an Acegi AuthenticationManager. Logic based on
+ * Acegi's BasicProcessingFilter.
+ *
+ * This handler requires an Acegi AuthenticationManager to operate. It can be set using the
+ * authenticationManager property. An Acegi UsernamePasswordAuthenticationToken is created
+ * with the username as principal and password as credentials.
+ *
+ * @author Arjen Poutsma
+ * @see org.acegisecurity.providers.UsernamePasswordAuthenticationToken
+ * @see org.acegisecurity.ui.basicauth.BasicProcessingFilter
+ * @since 1.5.0
+ */
+public class AcegiPlainTextPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler {
+
+ private AuthenticationManager authenticationManager;
+
+ private boolean ignoreFailure = false;
+
+ /** Sets the Acegi authentication manager. Required. */
+ public void setAuthenticationManager(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ }
+
+ public void setIgnoreFailure(boolean ignoreFailure) {
+ this.ignoreFailure = ignoreFailure;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(authenticationManager, "authenticationManager is required");
+ }
+
+ protected void handleUsernameTokenUnknown(WSPasswordCallback callback)
+ throws IOException, UnsupportedCallbackException {
+ String identifier = callback.getIdentifer();
+ try {
+ Authentication authResult = authenticationManager
+ .authenticate(new UsernamePasswordAuthenticationToken(identifier, callback.getPassword()));
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication success: " + authResult.toString());
+ }
+ SecurityContextHolder.getContext().setAuthentication(authResult);
+ }
+ catch (AuthenticationException failed) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication request for user '" + identifier + "' failed: " + failed.toString());
+ }
+ SecurityContextHolder.getContext().setAuthentication(null);
+ if (!ignoreFailure) {
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ }
+ }
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/package.html b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/package.html
new file mode 100644
index 00000000..f553860c
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/package.html
@@ -0,0 +1,6 @@
+
+
+Contains CallbackHandler implementations for WSS4J that use the Acegi
+ Security System for Spring.
+
+
\ No newline at end of file
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html
new file mode 100644
index 00000000..7bf2f27b
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/package.html
@@ -0,0 +1,5 @@
+
+
+Contains CallbackHandler implementations for WSS4J.
+
+
\ No newline at end of file
diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java
index 5450a6db..f9c85b63 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java
@@ -34,7 +34,7 @@ import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor;
import org.springframework.ws.soap.security.WsSecurityValidationException;
-import org.springframework.ws.soap.security.xwss.callback.CallbackHandlerChain;
+import org.springframework.ws.soap.security.xwss.callback.XwssCallbackHandlerChain;
/**
* WS-Security endpoint interceptor that is based on Sun's XML and Web Services Security package (XWSS). This
@@ -86,7 +86,7 @@ public class XwsSecurityInterceptor extends AbstractWsSecurityInterceptor implem
* @see #setCallbackHandler(javax.security.auth.callback.CallbackHandler)
*/
public void setCallbackHandlers(CallbackHandler[] callbackHandler) {
- this.callbackHandler = new CallbackHandlerChain(callbackHandler);
+ this.callbackHandler = new XwssCallbackHandlerChain(callbackHandler);
}
/** Sets the policy configuration to use for XWSS. Required. */
diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/KeyStoreCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/KeyStoreCallbackHandler.java
index 669f1a8e..225c8226 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/KeyStoreCallbackHandler.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/KeyStoreCallbackHandler.java
@@ -16,7 +16,6 @@
package org.springframework.ws.soap.security.xwss.callback;
-import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
@@ -42,11 +41,9 @@ import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;
import com.sun.xml.wss.impl.callback.SignatureKeyCallback;
import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback;
import org.apache.xml.security.utils.RFC2253Parser;
+
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.core.io.FileSystemResource;
-import org.springframework.core.io.Resource;
-import org.springframework.util.StringUtils;
-import org.springframework.ws.soap.security.support.KeyStoreFactoryBean;
+import org.springframework.ws.soap.security.support.KeyStoreUtils;
/**
* Callback handler that uses Java Security KeyStores to handle cryptographic callbacks. Allows for
@@ -562,43 +559,10 @@ public class KeyStoreCallbackHandler extends CryptographyCallbackHandler impleme
}
}
- /**
- * Loads the key store indicated by system properties. This method tries to load a key store by consulting the
- * following system properties:javax.net.ssl.keyStore, javax.net.ssl.keyStorePassword, and
- * javax.net.ssl.keyStoreType.
- *
- * If these properties specify a file with an appropriate password, the factory uses this file for the key store. If
- * that file does not exist, then a default, empty keystore is created.
- *
- * This behavior corresponds to the standard J2SDK behavior for SSL key stores.
- *
- * @see The
- * standard J2SDK SSL key store mechanism
- */
+ /** Loads the key store indicated by system properties. Delegates to {@link KeyStoreUtils#loadDefaultKeyStore()}. */
protected void loadDefaultKeyStore() {
- Resource location = null;
- String type = null;
- String password = null;
- String locationProperty = System.getProperty("javax.net.ssl.keyStore");
- if (StringUtils.hasLength(locationProperty)) {
- File f = new File(locationProperty);
- if (f.exists() && f.isFile() && f.canRead()) {
- location = new FileSystemResource(f);
- }
- String passwordProperty = System.getProperty("javax.net.ssl.keyStorePassword");
- if (StringUtils.hasLength(passwordProperty)) {
- password = passwordProperty;
- }
- type = System.getProperty("javax.net.ssl.trustStore");
- }
- // use the factory bean here, easier to setup
- KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();
- factoryBean.setLocation(location);
- factoryBean.setPassword(password);
- factoryBean.setType(type);
try {
- factoryBean.afterPropertiesSet();
- keyStore = (KeyStore) factoryBean.getObject();
+ keyStore = KeyStoreUtils.loadDefaultKeyStore();
if (logger.isDebugEnabled()) {
logger.debug("Loaded default key store");
}
@@ -608,54 +572,10 @@ public class KeyStoreCallbackHandler extends CryptographyCallbackHandler impleme
}
}
- /**
- * Loads a default trust store. This method uses the following algorithm: - If the system property
- *
javax.net.ssl.trustStore is defined, its value is loaded. If the
- * javax.net.ssl.trustStorePassword system property is also defined, its value is used as a password.
- * If the javax.net.ssl.trustStoreType system property is defined, its value is used as a key store
- * type.
- *
- * If javax.net.ssl.trustStore is defined but the specified file does not exist, then a default, empty
- * trust store is created. - If the
javax.net.ssl.trustStore system property was not
- * specified, but if the file $JAVA_HOME/lib/security/jssecacerts exists, that file is used.
- * Otherwise, - If the file
$JAVA_HOME/lib/security/cacerts exists, that file is used.
- *
- * This behavior corresponds to the standard J2SDK behavior for SSL trust stores.
- *
- * @see The
- * standard J2SDK SSL trust store mechanism
- */
+ /** Loads a default trust store. Delegates to {@link KeyStoreUtils#loadDefaultTrustStore()}. */
protected void loadDefaultTrustStore() {
- Resource location = null;
- String type = null;
- String password = null;
- String locationProperty = System.getProperty("javax.net.ssl.trustStore");
- if (StringUtils.hasLength(locationProperty)) {
- File f = new File(locationProperty);
- if (f.exists() && f.isFile() && f.canRead()) {
- location = new FileSystemResource(f);
- }
- String passwordProperty = System.getProperty("javax.net.ssl.trustStorePassword");
- if (StringUtils.hasLength(passwordProperty)) {
- password = passwordProperty;
- }
- type = System.getProperty("javax.net.ssl.trustStoreType");
- }
- else {
- String javaHome = System.getProperty("java.home");
- location = new FileSystemResource(javaHome + "/lib/security/jssecacerts");
- if (!location.exists()) {
- location = new FileSystemResource(javaHome + "/lib/security/cacerts");
- }
- }
- // use the factory bean here, easier to setup
- KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();
- factoryBean.setLocation(location);
- factoryBean.setPassword(password);
- factoryBean.setType(type);
try {
- factoryBean.afterPropertiesSet();
- trustStore = (KeyStore) factoryBean.getObject();
+ trustStore = KeyStoreUtils.loadDefaultTrustStore();
if (logger.isDebugEnabled()) {
logger.debug("Loaded default trust store");
}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChain.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/XwssCallbackHandlerChain.java
similarity index 79%
rename from security/src/main/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChain.java
rename to security/src/main/java/org/springframework/ws/soap/security/xwss/callback/XwssCallbackHandlerChain.java
index 35fc0050..63109f53 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChain.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/XwssCallbackHandlerChain.java
@@ -26,7 +26,7 @@ import com.sun.xml.wss.impl.callback.CertificateValidationCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import com.sun.xml.wss.impl.callback.TimestampValidationCallback;
-import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
+import org.springframework.ws.soap.security.callback.CallbackHandlerChain;
/**
* Represents a chain of CallbackHandlers. For each callback, each of the handlers is called in term. If a
@@ -35,16 +35,10 @@ import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
* @author Arjen Poutsma
* @since 1.0.0
*/
-public class CallbackHandlerChain extends AbstractCallbackHandler {
+public class XwssCallbackHandlerChain extends CallbackHandlerChain {
- private CallbackHandler[] callbackHandlers;
-
- public CallbackHandlerChain(CallbackHandler[] callbackHandlers) {
- this.callbackHandlers = callbackHandlers;
- }
-
- public void setCallbackHandlers(CallbackHandler[] callbackHandlers) {
- this.callbackHandlers = callbackHandlers;
+ public XwssCallbackHandlerChain(CallbackHandler[] callbackHandlers) {
+ super(callbackHandlers);
}
protected void handleInternal(Callback callback) throws IOException, UnsupportedCallbackException {
@@ -58,20 +52,7 @@ public class CallbackHandlerChain extends AbstractCallbackHandler {
handleTimestampValidationCallback((TimestampValidationCallback) callback);
}
else {
- boolean allUnsupported = true;
- for (int i = 0; i < callbackHandlers.length; i++) {
- CallbackHandler callbackHandler = callbackHandlers[i];
- try {
- callbackHandler.handle(new Callback[]{callback});
- allUnsupported = false;
- }
- catch (UnsupportedCallbackException ex) {
- // if an UnsupportedCallbackException occurs, go to the next handler
- }
- }
- if (allUnsupported) {
- throw new UnsupportedCallbackException(callback);
- }
+ super.handleInternal(callback);
}
}
@@ -97,8 +78,8 @@ public class CallbackHandlerChain extends AbstractCallbackHandler {
public void validate(TimestampValidationCallback.Request request)
throws TimestampValidationCallback.TimestampValidationException {
- for (int i = 0; i < callbackHandlers.length; i++) {
- CallbackHandler callbackHandler = callbackHandlers[i];
+ for (int i = 0; i < getCallbackHandlers().length; i++) {
+ CallbackHandler callbackHandler = getCallbackHandlers()[i];
try {
callbackHandler.handle(new Callback[]{callback});
callback.getResult();
@@ -124,8 +105,8 @@ public class CallbackHandlerChain extends AbstractCallbackHandler {
public boolean validate(PasswordValidationCallback.Request request)
throws PasswordValidationCallback.PasswordValidationException {
boolean allUnsupported = true;
- for (int i = 0; i < callbackHandlers.length; i++) {
- CallbackHandler callbackHandler = callbackHandlers[i];
+ for (int i = 0; i < getCallbackHandlers().length; i++) {
+ CallbackHandler callbackHandler = getCallbackHandlers()[i];
try {
callbackHandler.handle(new Callback[]{callback});
allUnsupported = false;
@@ -155,8 +136,8 @@ public class CallbackHandlerChain extends AbstractCallbackHandler {
public boolean validate(X509Certificate certificate)
throws CertificateValidationCallback.CertificateValidationException {
boolean allUnsupported = true;
- for (int i = 0; i < callbackHandlers.length; i++) {
- CallbackHandler callbackHandler = callbackHandlers[i];
+ for (int i = 0; i < getCallbackHandlers().length; i++) {
+ CallbackHandler callbackHandler = getCallbackHandlers()[i];
try {
callbackHandler.handle(new Callback[]{callback});
allUnsupported = false;
diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChainTest.java b/security/src/test/java/org/springframework/ws/soap/security/callback/CallbackHandlerChainTest.java
similarity index 94%
rename from security/src/test/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChainTest.java
rename to security/src/test/java/org/springframework/ws/soap/security/callback/CallbackHandlerChainTest.java
index 13d40537..33748b4e 100644
--- a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/CallbackHandlerChainTest.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/callback/CallbackHandlerChainTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.ws.soap.security.xwss.callback;
+package org.springframework.ws.soap.security.callback;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
@@ -46,7 +46,7 @@ public class CallbackHandlerChainTest extends TestCase {
chain.handle(new Callback[]{callback});
}
- public void testUnsupportedNormal() throws Exception {
+ public void testUnsupportedSupported() throws Exception {
CallbackHandlerChain chain = new CallbackHandlerChain(new CallbackHandler[]{unsupported, supported});
chain.handle(new Callback[]{callback});
}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorAcegiCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorAcegiCallbackHandlerTest.java
new file mode 100755
index 00000000..c5430080
--- /dev/null
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/AxiomWss4jMessageInterceptorAcegiCallbackHandlerTest.java
@@ -0,0 +1,6 @@
+package org.springframework.ws.soap.security.wss4j;
+
+public class AxiomWss4jMessageInterceptorAcegiCallbackHandlerTest
+ extends Wss4jMessageInterceptorAcegiCallbackHandlerTestCase {
+
+}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorAcegiCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorAcegiCallbackHandlerTest.java
new file mode 100755
index 00000000..bbbe7f9c
--- /dev/null
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorAcegiCallbackHandlerTest.java
@@ -0,0 +1,6 @@
+package org.springframework.ws.soap.security.wss4j;
+
+public class SaajWss4jMessageInterceptorAcegiCallbackHandlerTest
+ extends Wss4jMessageInterceptorAcegiCallbackHandlerTestCase {
+
+}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorAcegiCallbackHandlerTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorAcegiCallbackHandlerTestCase.java
new file mode 100755
index 00000000..33db8016
--- /dev/null
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorAcegiCallbackHandlerTestCase.java
@@ -0,0 +1,102 @@
+package org.springframework.ws.soap.security.wss4j;
+
+import java.util.Properties;
+
+import org.acegisecurity.Authentication;
+import org.acegisecurity.AuthenticationManager;
+import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.context.SecurityContextHolder;
+import org.acegisecurity.providers.TestingAuthenticationToken;
+import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+import org.acegisecurity.userdetails.memory.InMemoryDaoImpl;
+import org.apache.ws.security.WSConstants;
+import org.easymock.MockControl;
+
+import org.springframework.ws.context.DefaultMessageContext;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.server.EndpointInterceptor;
+import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.soap.security.wss4j.callback.acegi.AcegiDigestPasswordValidationCallbackHandler;
+import org.springframework.ws.soap.security.wss4j.callback.acegi.AcegiPlainTextPasswordValidationCallbackHandler;
+
+public abstract class Wss4jMessageInterceptorAcegiCallbackHandlerTestCase extends Wss4jTestCase {
+
+ private Properties users = new Properties();
+
+ private MockControl control;
+
+ private AuthenticationManager mock;
+
+ protected void onSetup() throws Exception {
+ control = MockControl.createControl(AuthenticationManager.class);
+ mock = (AuthenticationManager) control.getMock();
+ users.setProperty("Bert", "Ernie,ROLE_TEST");
+ }
+
+ protected void tearDown() throws Exception {
+ control.verify();
+ }
+
+ public void testValidateUsernameTokenPlainText() throws Exception {
+ EndpointInterceptor interceptor = prepareInterceptor("UsernameToken", true, false);
+ SoapMessage message = loadMessage("usernameTokenPlainText-soap.xml");
+ MessageContext messageContext = new DefaultMessageContext(message, getMessageFactory());
+ interceptor.handleRequest(messageContext, null);
+ assertValidateUsernameToken(message);
+ }
+
+ public void testValidateUsernameTokenDigest() throws Exception {
+ EndpointInterceptor interceptor = prepareInterceptor("UsernameToken", true, true);
+ SoapMessage message = loadMessage("usernameTokenDigest-soap.xml");
+ MessageContext messageContext = new DefaultMessageContext(message, getMessageFactory());
+ interceptor.handleRequest(messageContext, null);
+ assertValidateUsernameToken(message);
+ }
+
+ protected void assertValidateUsernameToken(SoapMessage message) throws Exception {
+ Object result = getMessage(message);
+ assertNotNull("No result returned", result);
+ assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security",
+ getDocument(message));
+ Authentication authentication = SecurityContextHolder.getContext()
+ .getAuthentication();
+ assertNotNull("authentication must not be null", authentication);
+ }
+
+ protected EndpointInterceptor prepareInterceptor(String actions, boolean validating, boolean digest)
+ throws Exception {
+ Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
+ if (validating) {
+ interceptor.setValidationActions(actions);
+ }
+ else {
+ interceptor.setSecurementActions(actions);
+ }
+ if (digest) {
+ AcegiDigestPasswordValidationCallbackHandler callbackHandler =
+ new AcegiDigestPasswordValidationCallbackHandler();
+ InMemoryDaoImpl userDetailsService = new InMemoryDaoImpl();
+ userDetailsService.setUserProperties(users);
+ userDetailsService.afterPropertiesSet();
+ callbackHandler.setUserDetailsService(userDetailsService);
+ interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
+ interceptor.setValidationCallbackHandler(callbackHandler);
+ interceptor.afterPropertiesSet();
+ }
+ else {
+ AcegiPlainTextPasswordValidationCallbackHandler callbackHandler =
+ new AcegiPlainTextPasswordValidationCallbackHandler();
+ Authentication authResult = new TestingAuthenticationToken("Bert", "Ernie", new GrantedAuthority[0]);
+ control.expectAndReturn(mock.authenticate(new UsernamePasswordAuthenticationToken("Bert", "Ernie")),
+ authResult);
+ callbackHandler.setAuthenticationManager(mock);
+ callbackHandler.afterPropertiesSet();
+ interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
+ interceptor.setValidationCallbackHandler(callbackHandler);
+ interceptor.afterPropertiesSet();
+ }
+ control.replay();
+ return interceptor;
+ }
+}
+
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java
index 5e107ff3..bc0eaee3 100755
--- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorEncryptionTestCase.java
@@ -8,7 +8,7 @@ import org.w3c.dom.Document;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.security.wss4j.callback.SimpleCallbackHandler;
+import org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean;
public abstract class Wss4jMessageInterceptorEncryptionTestCase extends Wss4jTestCase {
@@ -20,8 +20,8 @@ public abstract class Wss4jMessageInterceptorEncryptionTestCase extends Wss4jTes
interceptor.setValidationActions("Encrypt");
interceptor.setSecurementActions("Encrypt");
- SimpleCallbackHandler callbackHandler = new SimpleCallbackHandler();
- callbackHandler.setKeyPassword("123456");
+ KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
+ callbackHandler.setPrivateKeyPassword("123456");
interceptor.setValidationCallbackHandler(callbackHandler);
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
@@ -63,6 +63,5 @@ public abstract class Wss4jMessageInterceptorEncryptionTestCase extends Wss4jTes
Document document = getDocument(message);
assertXpathExists("Encryption error", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/xenc:EncryptedKey",
document);
- //TODO see why the clear message appears in the unit test
}
}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java
index 5c845f99..18520314 100755
--- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java
@@ -8,7 +8,7 @@ import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapHeaderElement;
import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.security.wss4j.callback.SimpleCallbackHandler;
+import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler;
public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCase {
@@ -21,7 +21,7 @@ public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCas
interceptor.setValidateRequest(true);
interceptor.setSecureResponse(true);
interceptor.setValidationActions("UsernameToken");
- SimpleCallbackHandler callbackHandler = new SimpleCallbackHandler();
+ SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
callbackHandler.setUsers(users);
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.afterPropertiesSet();
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java
index 038707fc..6b347015 100755
--- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSignTestCase.java
@@ -9,7 +9,6 @@ import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.security.wss4j.callback.SimpleCallbackHandler;
import org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean;
public abstract class Wss4jMessageInterceptorSignTestCase extends Wss4jTestCase {
@@ -19,8 +18,6 @@ public abstract class Wss4jMessageInterceptorSignTestCase extends Wss4jTestCase
protected void onSetup() throws Exception {
interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("Signature");
- SimpleCallbackHandler callbackHandler = new SimpleCallbackHandler();
- interceptor.setValidationCallbackHandler(callbackHandler);
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
Properties cryptoFactoryBeanConfig = new Properties();
@@ -61,7 +58,6 @@ public abstract class Wss4jMessageInterceptorSignTestCase extends Wss4jTestCase
interceptor.secureMessage(message, messageContext);
assertNotNull("No result returned", response);
Document document = getDocument((SoapMessage) response);
- message.writeTo(System.out);
assertXpathExists("Absent SignatureConfirmation element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse11:SignatureConfirmation", document);
}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java
index 5c82bb16..e437cc60 100755
--- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorUsernameTokenTestCase.java
@@ -8,7 +8,7 @@ import org.w3c.dom.Document;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.security.wss4j.callback.SimpleCallbackHandler;
+import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler;
public abstract class Wss4jMessageInterceptorUsernameTokenTestCase extends Wss4jTestCase {
@@ -96,16 +96,16 @@ public abstract class Wss4jMessageInterceptorUsernameTokenTestCase extends Wss4j
else {
interceptor.setSecurementActions(actions);
}
- SimpleCallbackHandler callbackHandler = new SimpleCallbackHandler();
+ SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
callbackHandler.setUsers(users);
if (digest) {
- callbackHandler.setPasswordDigestRequired(true);
- callbackHandler.setPasswordPlainTextRequired(false);
+// callbackHandler.setPasswordDigestRequired(true);
+// callbackHandler.setPasswordPlainTextRequired(false);
interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
}
else {
- callbackHandler.setPasswordDigestRequired(false);
- callbackHandler.setPasswordPlainTextRequired(true);
+// callbackHandler.setPasswordDigestRequired(false);
+// callbackHandler.setPasswordPlainTextRequired(true);
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
}
interceptor.setValidationCallbackHandler(callbackHandler);