SWS-886 Update to WSS4J 2.0.x / XMLSec 2.0.x

This commit is contained in:
Jamin Hitchcock
2015-08-12 21:21:16 -05:00
committed by Greg Turnquist
parent 5b07910276
commit f6f11b09d1
64 changed files with 3985 additions and 1 deletions

3
.gitignore vendored
View File

@@ -16,3 +16,6 @@ out
.gradle
_site
/.classpath
/.project
/.settings/

View File

@@ -250,7 +250,9 @@ project('spring-ws-security') {
optional("com.sun.xml.wss:xws-security:3.0") {
exclude group: 'javax.xml.crypto', module: 'xmldsig'
}
optional("org.apache.ws.security:wss4j:1.6.15")
compile("org.apache.ws.security:wss4j:1.6.19")
compile("org.apache.wss4j:wss4j-ws-security-dom:2.0.5")
// SOAP
provided("com.sun.xml.messaging.saaj:saaj-impl:1.3.19") // required for XWSS

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2005-2012 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.wss4j2;
import java.util.List;
import java.util.Properties;
import org.springframework.ws.context.MessageContext;
import org.w3c.dom.Document;
import org.apache.wss4j.common.ConfigurationConstants;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.HandlerAction;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandler;
/**
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
class Wss4jHandler extends WSHandler {
/** Keys are constants from {@link WSHandlerConstants}; values are strings. */
private Properties options = new Properties();
private String securementPassword;
private Crypto securementEncryptionCrypto;
private Crypto securementSignatureCrypto;
Wss4jHandler() {
// set up default handler properties
options.setProperty(ConfigurationConstants.MUST_UNDERSTAND, Boolean.toString(true));
options.setProperty(ConfigurationConstants.ENABLE_SIGNATURE_CONFIRMATION, Boolean.toString(true));
}
public void doSenderAction(
Document doc,
RequestData reqData,
List<HandlerAction> actions,
boolean isRequest) throws WSSecurityException
{
super.doSenderAction(doc, reqData, actions, isRequest);
}
@Override
protected boolean checkReceiverResultsAnyOrder(List<WSSecurityEngineResult> wsResult, List<Integer> actions) {
return super.checkReceiverResultsAnyOrder(wsResult, actions);
}
void setOption(String key, String value) {
options.setProperty(key, value);
}
void setOption(String key, boolean value) {
options.setProperty(key, Boolean.toString(value));
}
@Override
public Object getOption(String key) {
return options.getProperty(key);
}
void setSecurementPassword(String securementPassword) {
this.securementPassword = securementPassword;
}
void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) {
this.securementEncryptionCrypto = securementEncryptionCrypto;
}
void setSecurementSignatureCrypto(Crypto securementSignatureCrypto) {
this.securementSignatureCrypto = securementSignatureCrypto;
}
@Override
public String getPassword(Object msgContext) {
return securementPassword;
}
@Override
public Object getProperty(Object msgContext, String key) {
return ((MessageContext) msgContext).getProperty(key);
}
@Override
protected Crypto loadEncryptionCrypto(RequestData reqData) throws WSSecurityException {
return securementEncryptionCrypto;
}
@Override
public Crypto loadSignatureCrypto(RequestData reqData) throws WSSecurityException {
return securementSignatureCrypto;
}
@Override
public void setPassword(Object msgContext, String password) {
securementPassword = password;
}
@Override
public void setProperty(Object msgContext, String key, Object value) {
((MessageContext) msgContext).setProperty(key, value);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2005-2014 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.wss4j2;
import javax.xml.namespace.QName;
import org.springframework.ws.soap.security.WsSecurityFaultException;
/**
* WSS4J-specific version of the {@link WsSecurityFaultException}.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
@SuppressWarnings("serial")
public class Wss4jSecurityFaultException extends WsSecurityFaultException {
public Wss4jSecurityFaultException(QName faultCode, String faultString, String faultActor) {
super(faultCode, faultString, faultActor);
}
}

View File

@@ -0,0 +1,784 @@
/*
* Copyright 2005-2014 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.wss4j2;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ConfigurationConstants;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.WSSConfig;
import org.apache.wss4j.dom.WSSecurityEngine;
import org.apache.wss4j.dom.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.HandlerAction;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.dom.message.token.Timestamp;
import org.apache.wss4j.dom.util.WSSecurityUtil;
import org.apache.wss4j.dom.validate.Credential;
import org.apache.wss4j.dom.validate.SignatureTrustValidator;
import org.apache.wss4j.dom.validate.TimestampValidator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
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;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import org.springframework.ws.soap.security.wss4j2.callback.UsernameTokenPrincipalCallback;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* A WS-Security endpoint interceptor based on Apache's WSS4J. This interceptor supports messages created by the {@link
* org.springframework.ws.soap.axiom.AxiomSoapMessageFactory} and the {@link org.springframework.ws.soap.saaj.SaajSoapMessageFactory}.
*
* <p>The validation and securement actions executed by this interceptor are configured via {@code validationActions}
* and {@code securementActions} properties, respectively. Actions should be passed as a space-separated strings.
*
* <p>Valid <strong>validation</strong> actions are:
*
* <blockquote>
* <table>
* <tr><th>Validation action</th><th>Description</th></tr>
* <tr><td>{@code UsernameToken}</td><td>Validates username token</td></tr>
* <tr><td>{@code Timestamp}</td><td>Validates the timestamp</td></tr>
* <tr><td>{@code Encrypt}</td><td>Decrypts the message</td></tr>
* <tr><td>{@code Signature}</td><td>Validates the signature</td></tr>
* <tr><td>{@code NoSecurity}</td><td>No action performed</td></tr>
* </table></blockquote>
* <p>
* <strong>Securement</strong> actions are:
*
* <blockquote>
* <table>
* <tr><th>Securement action</th><th>Description</th></tr>
* <tr><td>{@code UsernameToken}</td><td>Adds a username token</td></tr>
* <tr><td>{@code UsernameTokenSignature}</td><td>Adds a username token and a signature username token secret key</td></tr>
* <tr><td>{@code Timestamp}</td><td>Adds a timestamp</td></tr>
* <tr><td>{@code Encrypt}</td><td>Encrypts the response</td></tr>
* <tr><td>{@code Signature}</td><td>Signs the response</td></tr>
* <tr><td>{@code NoSecurity}</td><td>No action performed</td></tr>
* </table></blockquote>
*
* <p>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
* @author Greg Turnquist
* @author Jamin Hitchcock
* @see <a href="http://ws.apache.org/wss4j/">Apache WSS4J 2.0</a>
* @since 2.3.0
*/
public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor implements InitializingBean {
public static final String SECUREMENT_USER_PROPERTY_NAME = "Wss4jSecurityInterceptor.securementUser";
private String securementActions;
private String securementUsername;
private CallbackHandler validationCallbackHandler;
private String validationActions;
private List<Integer> validationActionsVector;
private String validationActor;
private Crypto validationDecryptionCrypto;
private Crypto validationSignatureCrypto;
private boolean timestampStrict = true;
private boolean enableSignatureConfirmation;
private int validationTimeToLive = 300;
private int securementTimeToLive = 300;
private int futureTimeToLive = 60;
private WSSConfig wssConfig;
private final Wss4jHandler handler = new Wss4jHandler();
private final WSSecurityEngine securityEngine = new WSSecurityEngine();
private boolean enableRevocation;
private boolean bspCompliant;
private boolean securementUseDerivedKey;
// Allow RSA 15 to maintain default behavior
private boolean allowRSA15KeyTransportAlgorithm = true;
// To maintain same behavior as default, this flag is set to true
private boolean removeSecurityHeader = true;
public void setSecurementActions(String securementActions) {
this.securementActions = securementActions;
}
/**
* The actor name of the {@code wsse:Security} header.
*
* <p>If this parameter is omitted, the actor name is not set.
*
* <p>The value of the actor or role has to match the receiver's setting or may contain standard values.
*/
public void setSecurementActor(String securementActor) {
handler.setOption(WSHandlerConstants.ACTOR, securementActor);
}
public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) {
handler.setSecurementEncryptionCrypto(securementEncryptionCrypto);
}
/**
* Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type
* {@code IssuerSerial}. For possible encryption key identifier types refer to {@link
* org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For encryption {@code IssuerSerial},
* {@code X509KeyIdentifier}, {@code DirectReference}, {@code Thumbprint},
* {@code SKIKeyIdentifier}, and {@code EmbeddedKeyName} are valid only.
*/
public void setSecurementEncryptionKeyIdentifier(String securementEncryptionKeyIdentifier) {
handler.setOption(WSHandlerConstants.ENC_KEY_ID, securementEncryptionKeyIdentifier);
}
/**
* Defines which algorithm to use to encrypt the generated symmetric key. Currently WSS4J supports {@link
* WSConstants#KEYTRANSPORT_RSA15} and {@link WSConstants#KEYTRANSPORT_RSAOEP}.
*/
public void setSecurementEncryptionKeyTransportAlgorithm(String securementEncryptionKeyTransportAlgorithm) {
handler.setOption(WSHandlerConstants.ENC_KEY_TRANSPORT, securementEncryptionKeyTransportAlgorithm);
}
/**
* Property to define which parts of the request shall be encrypted.
*
* <p>The value of this property is a list of semicolon separated element names that identify the elements to encrypt.
* An encryption mode specifier and a namespace identification, each inside a pair of curly brackets, may precede
* each element name.
*
* <p>The encryption mode specifier is either {@code {Content}} or {@code {Element}}. Please refer to the W3C
* XML Encryption specification about the differences between Element and Content encryption. The encryption mode
* defaults to {@code Content} if it is omitted. Example of a list:
* <pre>
* &lt;property name="securementEncryptionParts"
* value="{Content}{http://example.org/paymentv2}CreditCard;
* {Element}{}UserName" />
* </pre>
* The the first entry of the list identifies the element {@code CreditCard} in the namespace
* {@code http://example.org/paymentv2}, and will encrypt its content. Be aware that the element name, the
* namespace identifier, and the encryption modifier are case sensitive.
*
* <p>The encryption modifier and the namespace identifier can be omitted. In this case the encryption mode defaults to
* {@code Content} and the namespace is set to the SOAP namespace.
*
* <p>An empty encryption mode defaults to {@code Content}, an empty namespace identifier defaults to the SOAP
* namespace. The second line of the example defines {@code Element} as encryption mode for an
* {@code UserName} element in the SOAP namespace.
*
* <p>To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case
* sensitive string)
*
* <p>If no list is specified, the handler encrypts the SOAP Body in {@code Content} mode by default.
*/
public void setSecurementEncryptionParts(String securementEncryptionParts) {
handler.setOption(WSHandlerConstants.ENCRYPTION_PARTS, securementEncryptionParts);
}
/**
* Defines which symmetric encryption algorithm to use. WSS4J supports the following alorithms: {@link
* WSConstants#TRIPLE_DES}, {@link WSConstants#AES_128}, {@link WSConstants#AES_256}, and {@link
* WSConstants#AES_192}. Except for AES 192 all of these algorithms are required by the XML Encryption
* specification.
*/
public void setSecurementEncryptionSymAlgorithm(String securementEncryptionSymAlgorithm) {
this.handler.setOption(WSHandlerConstants.ENC_SYM_ALGO, securementEncryptionSymAlgorithm);
}
/**
* The user's name for encryption.
*
* <p>The encryption functions uses the public key of this user's certificate to encrypt the generated symmetric key.
*
* <p>If this parameter is not set, then the encryption function falls back to the {@link
* org.apache.ws.security.handler.WSHandlerConstants#USER} parameter to get the certificate.
*
* <p>If <b>only</b> encryption of the SOAP body data is requested, it is recommended to use this parameter to define
* the username. The application can then use the standard user and password functions (see example at {@link
* org.apache.ws.security.handler.WSHandlerConstants#USER} to enable HTTP authentication functions.
*
* <p>Encryption only does not authenticate a user / sender, therefore it does not need a password.
*
* <p>Placing the username of the encryption certificate in the configuration file is not a security risk, because the
* public key of that certificate is used only.
*/
public void setSecurementEncryptionUser(String securementEncryptionUser) {
handler.setOption(WSHandlerConstants.ENCRYPTION_USER, securementEncryptionUser);
}
public void setSecurementPassword(String securementPassword) {
this.handler.setSecurementPassword(securementPassword);
}
/**
* Specific parameter for UsernameToken action to define the encoding of the passowrd.
*
* <p>The parameter can be set to either {@link WSConstants#PW_DIGEST} or to {@link WSConstants#PW_TEXT}.
*
* <p>The default setting is PW_DIGEST.
*/
public void setSecurementPasswordType(String securementUsernameTokenPasswordType) {
handler.setOption(WSHandlerConstants.PASSWORD_TYPE, securementUsernameTokenPasswordType);
}
/**
* Defines which signature algorithm to use.
* @see WSConstants#RSA
* @see WSConstants#DSA
*/
public void setSecurementSignatureAlgorithm(String securementSignatureAlgorithm) {
handler.setOption(WSHandlerConstants.SIG_ALGO, securementSignatureAlgorithm);
}
/**
* Defines which signature digest algorithm to use.
*/
public void setSecurementSignatureDigestAlgorithm(String digestAlgorithm) {
handler.setOption(WSHandlerConstants.SIG_DIGEST_ALGO, digestAlgorithm);
}
public void setSecurementSignatureCrypto(Crypto securementSignatureCrypto) {
handler.setSecurementSignatureCrypto(securementSignatureCrypto);
}
/**
* Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type
* {@code IssuerSerial}. For possible signature key identifier types refer to {@link
* org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For signature {@code IssuerSerial} and
* {@code DirectReference} are valid only.
*/
public void setSecurementSignatureKeyIdentifier(String securementSignatureKeyIdentifier) {
handler.setOption(WSHandlerConstants.SIG_KEY_ID, securementSignatureKeyIdentifier);
}
/**
* Property to define which parts of the request shall be signed.
*
* <p>Refer to {@link #setSecurementEncryptionParts(String)} for a detailed description of the format of the value
* string.
*
* <p>If this property is not specified the handler signs the SOAP Body by default.
*
* <p>The WS Security specifications define several formats to transfer the signature tokens (certificates) or
* references to these tokens. Thus, the plain element name {@code Token} signs the token and takes care of the
* different formats.
*
* <p>To sign the SOAP body <b>and</b> the signature token the value of this parameter must contain:
* <pre>
* &lt;property name="securementSignatureParts"
* value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body; Token" />
* </pre>
* To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case
* sensitive string)
*
* <p>If there is no other element in the request with a local name of {@code Body} then the SOAP namespace
* identifier can be empty ({@code {}}).
*/
public void setSecurementSignatureParts(String securementSignatureParts) {
handler.setOption(WSHandlerConstants.SIGNATURE_PARTS, securementSignatureParts);
}
/**
* The user's name for signature.
*
* <p>This name is used as the alias name in the keystore to get user's
* certificate and private key to perform signing.
*
* <p>If this parameter is not set, then the signature
* function falls back to the alias specified by {@link #setSecurementUsername(String)}.
*
*/
public void setSecurementSignatureUser(String securementSignatureUser) {
handler.setOption(WSHandlerConstants.SIGNATURE_USER, securementSignatureUser);
}
/** Sets the username for securement username token or/and the alias of the private key for securement signature */
public void setSecurementUsername(String securementUsername) {
this.securementUsername = securementUsername;
}
/** Sets the time to live on the outgoing message */
public void setSecurementTimeToLive(int securementTimeToLive) {
if (securementTimeToLive <= 0) {
throw new IllegalArgumentException("timeToLive must be positive");
}
this.securementTimeToLive = securementTimeToLive;
}
/**
* Enables the derivation of keys as per the UsernameTokenProfile 1.1 spec. Default is {@code true}.
*/
public void setSecurementUseDerivedKey(boolean securementUseDerivedKey) {
this.securementUseDerivedKey = securementUseDerivedKey;
}
/** Sets the server-side time to live */
public void setValidationTimeToLive(int validationTimeToLive) {
if (validationTimeToLive <= 0) {
throw new IllegalArgumentException("timeToLive must be positive");
}
this.validationTimeToLive = validationTimeToLive;
}
/** Sets the validation actions to be executed by the interceptor. */
public void setValidationActions(String actions) {
this.validationActions = actions;
try {
validationActionsVector = WSSecurityUtil.decodeAction(actions);
}
catch (WSSecurityException ex) {
throw new IllegalArgumentException(ex);
}
}
public void setValidationActor(String validationActor) {
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;
}
/** Sets the Crypto to use to verify the signature of incoming messages */
public void setValidationSignatureCrypto(Crypto signatureCrypto) {
this.validationSignatureCrypto = signatureCrypto;
}
/** Whether to enable signatureConfirmation or not. By default signatureConfirmation is enabled */
public void setEnableSignatureConfirmation(boolean enableSignatureConfirmation) {
handler.setOption(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, enableSignatureConfirmation);
this.enableSignatureConfirmation = enableSignatureConfirmation;
}
/** Sets if the generated timestamp header's precision is in milliseconds. */
public void setTimestampPrecisionInMilliseconds(boolean timestampPrecisionInMilliseconds) {
handler.setOption(WSHandlerConstants.TIMESTAMP_PRECISION, timestampPrecisionInMilliseconds);
}
/** Sets whether or not timestamp verification is done with the server-side time to live */
public void setTimestampStrict(boolean timestampStrict) {
this.timestampStrict = timestampStrict;
}
/**
* Enables the {@code mustUnderstand} attribute on WS-Security headers on outgoing messages. Default is
* {@code true}.
*/
public void setSecurementMustUnderstand(boolean securementMustUnderstand) {
handler.setOption(WSHandlerConstants.MUST_UNDERSTAND, securementMustUnderstand);
}
/**
* Sets whether or not a {@code Nonce} element is added to the
* {@code UsernameToken}s. Default is {@code false}.
*/
public void setSecurementUsernameTokenNonce(boolean securementUsernameTokenNonce) {
handler.setOption(ConfigurationConstants.ADD_USERNAMETOKEN_NONCE, securementUsernameTokenNonce);
}
/**
* Sets whether or not a {@code Created} element is added to the
* {@code UsernameToken}s. Default is {@code false}.
*/
public void setSecurementUsernameTokenCreated(boolean securementUsernameTokenCreated)
{
handler.setOption(ConfigurationConstants.ADD_USERNAMETOKEN_CREATED, securementUsernameTokenCreated);
}
/**
* Sets the web service specification settings.
* <p>
* The default settings follow the latest OASIS and changing anything might violate the OASIS specs.
*
* @param config web service security configuration or {@code null} to use default settings
*/
public void setWssConfig(WSSConfig config) {
securityEngine.setWssConfig(config);
wssConfig = config;
}
/**
* Set whether to enable CRL checking or not when verifying trust in a certificate.
*/
public void setEnableRevocation(boolean enableRevocation) {
this.enableRevocation = enableRevocation;
}
/**
* Set the WS-I Basic Security Profile compliance mode. Default is {@code true}.
*/
public void setBspCompliant(boolean bspCompliant) {
this.handler.setOption(WSHandlerConstants.IS_BSP_COMPLIANT, bspCompliant);
this.bspCompliant = bspCompliant;
}
/**
* Sets whether the RSA 1.5 key transport algorithm is allowed.
*/
public void setAllowRSA15KeyTransportAlgorithm(boolean allow)
{
this.allowRSA15KeyTransportAlgorithm = allow;
}
/**
* Sets the time in seconds in the future within which the Created time of an
* incoming Timestamp is valid. The default is 60 seconds.
*/
public void setFutureTimeToLive(int futureTimeToLive) {
if (futureTimeToLive <= 0) {
throw new IllegalArgumentException("futureTimeToLive must be positive");
}
this.futureTimeToLive = futureTimeToLive;
}
public boolean getRemoveSecurityHeader() {
return removeSecurityHeader;
}
public void setRemoveSecurityHeader(boolean removeSecurityHeader) {
this.removeSecurityHeader = removeSecurityHeader;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.isTrue(validationActions != null || securementActions != null,
"validationActions or securementActions are required");
if (validationActions != null) {
if (validationActionsVector.contains(WSConstants.UT)) {
Assert.notNull(validationCallbackHandler, "validationCallbackHandler is required");
}
if (validationActionsVector.contains(WSConstants.SIGN)) {
Assert.notNull(validationSignatureCrypto, "validationSignatureCrypto is required");
}
}
// securement actions are not to be validated at start up as they could
// be configured dynamically via the message context
// allow for qualified password types for .Net interoperability
securityEngine.getWssConfig().setAllowNamespaceQualifiedPasswordTypes(true);
}
@Override
protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecuritySecurementException {
List<HandlerAction> securementActionsVector = new ArrayList<HandlerAction>();
try {
securementActionsVector = WSSecurityUtil.decodeHandlerAction(securementActions, wssConfig);
}
catch (WSSecurityException ex) {
throw new Wss4jSecuritySecurementException(ex.getMessage(), ex);
}
if (securementActionsVector.isEmpty() && !enableSignatureConfirmation) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Securing message [" + soapMessage + "] with actions [" + securementActions + "]");
}
RequestData requestData = initializeRequestData(messageContext);
Document envelopeAsDocument = soapMessage.getDocument();
try {
handler.doSenderAction(envelopeAsDocument, requestData, securementActionsVector, false);
}
catch (WSSecurityException ex) {
throw new Wss4jSecuritySecurementException(ex.getMessage(), ex);
}
soapMessage.setDocument(envelopeAsDocument);
}
/**
* Creates and initializes a request data for the given message context.
*
* @param messageContext the message context
* @return the request data
*/
protected RequestData initializeRequestData(MessageContext messageContext) {
RequestData requestData = new RequestData();
requestData.setMsgContext(messageContext);
// reads securementUsername first from the context then from the property
String contextUsername = (String) messageContext.getProperty(SECUREMENT_USER_PROPERTY_NAME);
if (StringUtils.hasLength(contextUsername)) {
requestData.setUsername(contextUsername);
}
else {
requestData.setUsername(securementUsername);
}
requestData.setTimeToLive(securementTimeToLive);
requestData.setUseDerivedKeyForMAC(securementUseDerivedKey);
requestData.setWssConfig(wssConfig);
messageContext.setProperty(WSHandlerConstants.TTL_TIMESTAMP, Integer.toString(securementTimeToLive));
return requestData;
}
/**
* Creates and initializes a request data for the given message context.
*
* @param messageContext the message context
* @return the request data
*/
protected RequestData initializeValidationRequestData(MessageContext messageContext) {
RequestData requestData = new RequestData();
requestData.setMsgContext(messageContext);
requestData.setWssConfig(wssConfig);
requestData.setDecCrypto(validationDecryptionCrypto);
requestData.setSigVerCrypto(validationSignatureCrypto);
requestData.setCallbackHandler(validationCallbackHandler);
messageContext.setProperty(WSHandlerConstants.TTL_TIMESTAMP, Integer.toString(validationTimeToLive));
requestData.setAllowRSA15KeyTransportAlgorithm(allowRSA15KeyTransportAlgorithm);
requestData.setDisableBSPEnforcement(!bspCompliant);
if (requestData.getBSPEnforcer() != null)
{
requestData.getBSPEnforcer().setDisableBSPRules(!bspCompliant);
}
return requestData;
}
@Override
protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecurityValidationException {
if (logger.isDebugEnabled()) {
logger.debug("Validating message [" + soapMessage + "] with actions [" + validationActions + "]");
}
if (validationActionsVector.contains(WSConstants.NO_SECURITY)) {
return;
}
Document envelopeAsDocument = soapMessage.getDocument();
// Header processing
try {
RequestData validationData = initializeValidationRequestData(messageContext);
String actor = validationActor;
if (actor == null) {
actor = "";
}
Element elem = WSSecurityUtil.getSecurityHeader(envelopeAsDocument, actor);
List<WSSecurityEngineResult> results = securityEngine
.processSecurityHeader(elem, validationData);
// Results verification
if (CollectionUtils.isEmpty(results)) {
throw new Wss4jSecurityValidationException("No WS-Security header found");
}
checkResults(results, validationActionsVector);
// puts the results in the context
// useful for Signature Confirmation
updateContextWithResults(messageContext, results);
verifyCertificateTrust(results);
verifyTimestamp(results);
processPrincipal(results);
}
catch (WSSecurityException ex) {
throw new Wss4jSecurityValidationException(ex.getMessage(), ex);
}
soapMessage.setDocument(envelopeAsDocument);
if (this.getRemoveSecurityHeader()) {
soapMessage.getEnvelope().getHeader().removeHeaderElement(WS_SECURITY_NAME);
}
}
/**
* Checks whether the received headers match the configured validation actions. Subclasses could override this method
* for custom verification behavior.
*
*
* @param results the results of the validation function
* @param validationActions the decoded validation actions
* @throws Wss4jSecurityValidationException if the results are deemed invalid
*/
protected void checkResults(List<WSSecurityEngineResult> results, List<Integer> validationActions)
throws Wss4jSecurityValidationException {
if (!handler.checkReceiverResultsAnyOrder(results, validationActions)) {
throw new Wss4jSecurityValidationException("Security processing failed (actions mismatch)");
}
}
/**
* Puts the results of WS-Security headers processing in the message context. Some actions like Signature
* Confirmation require this.
*/
@SuppressWarnings("unchecked")
private void updateContextWithResults(MessageContext messageContext, List<WSSecurityEngineResult> results) {
List<WSHandlerResult> handlerResults;
if ((handlerResults = (List<WSHandlerResult>) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) {
handlerResults = new ArrayList<WSHandlerResult>();
messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults);
}
WSHandlerResult rResult = new WSHandlerResult(validationActor, results);
handlerResults.add(0, rResult);
messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults);
}
/** Verifies the trust of a certificate. */
protected void verifyCertificateTrust(List<WSSecurityEngineResult> results) throws WSSecurityException {
WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
if (actionResult != null) {
X509Certificate returnCert =
(X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
Credential credential = new Credential();
credential.setCertificates(new X509Certificate[] { returnCert});
RequestData requestData = new RequestData();
requestData.setSigVerCrypto(validationSignatureCrypto);
requestData.setEnableRevocation(enableRevocation);
SignatureTrustValidator validator = new SignatureTrustValidator();
validator.validate(credential, requestData);
}
}
/** Verifies the timestamp. */
protected void verifyTimestamp(List<WSSecurityEngineResult> results) throws WSSecurityException {
WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.TS);
if (actionResult != null) {
Timestamp timestamp = (Timestamp) actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
if (timestamp != null && timestampStrict) {
Credential credential = new Credential();
credential.setTimestamp(timestamp);
RequestData requestData = new RequestData();
WSSConfig config = WSSConfig.getNewInstance();
config.setTimeStampTTL(validationTimeToLive);
config.setTimeStampStrict(timestampStrict);
config.setTimeStampFutureTTL(futureTimeToLive);
requestData.setWssConfig(config);
TimestampValidator validator = new TimestampValidator();
validator.validate(credential, requestData);
}
}
}
private void processPrincipal(List<WSSecurityEngineResult> results) {
WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.UT);
if (actionResult != null) {
Principal principal = (Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
if (principal != null && principal instanceof WSUsernameTokenPrincipalImpl) {
WSUsernameTokenPrincipalImpl usernameTokenPrincipal = (WSUsernameTokenPrincipalImpl) principal;
UsernameTokenPrincipalCallback callback = new UsernameTokenPrincipalCallback(usernameTokenPrincipal);
try {
validationCallbackHandler.handle(new Callback[]{callback});
}
catch (IOException ex) {
logger.warn("Principal callback resulted in IOException", ex);
}
catch (UnsupportedCallbackException ex) {
// ignore
}
}
}
}
@Override
protected void cleanUp() {
if (validationCallbackHandler != null) {
try {
CleanupCallback cleanupCallback = new CleanupCallback();
validationCallbackHandler.handle(new Callback[]{cleanupCallback});
}
catch (IOException ex) {
logger.warn("Cleanup callback resulted in IOException", ex);
}
catch (UnsupportedCallbackException ex) {
// ignore
}
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2005-2014 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.wss4j2;
import org.springframework.ws.soap.security.WsSecuritySecurementException;
/**
* WSS4J-specific version of the {@link WsSecuritySecurementException}.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
@SuppressWarnings("serial")
public class Wss4jSecuritySecurementException extends WsSecuritySecurementException {
public Wss4jSecuritySecurementException(String msg) {
super(msg);
}
public Wss4jSecuritySecurementException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2005-2014 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.wss4j2;
import org.springframework.ws.soap.security.WsSecurityValidationException;
/**
* WSS4J-specific version of the {@link WsSecurityValidationException}.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
@SuppressWarnings("serial")
public class Wss4jSecurityValidationException extends WsSecurityValidationException {
public Wss4jSecurityValidationException(String msg) {
super(msg);
}
public Wss4jSecurityValidationException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright 2005-2012 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.wss4j2.callback;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
/**
* Abstract base class for {@link javax.security.auth.callback.CallbackHandler} implementations that handle {@link
* WSPasswordCallback} callbacks.
*
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallbackHandler {
/**
* Handles {@link WSPasswordCallback} callbacks. Inspects the callback {@link WSPasswordCallback#getUsage() usage}
* code, and calls the various {@code handle*} template methods.
*
* @param callback the callback
* @throws IOException in case of I/O errors
* @throws UnsupportedCallbackException when the callback is not supported
*/
@Override
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.SECURITY_CONTEXT_TOKEN:
handleSecurityContextToken(passwordCallback);
break;
case WSPasswordCallback.CUSTOM_TOKEN:
handleCustomToken(passwordCallback);
break;
case WSPasswordCallback.SECRET_KEY:
handleSecretKey(passwordCallback);
break;
default:
throw new UnsupportedCallbackException(callback,
"Unknown usage [" + passwordCallback.getUsage() + "]");
}
}
else if (callback instanceof CleanupCallback) {
handleCleanup((CleanupCallback) callback);
}
else if (callback instanceof UsernameTokenPrincipalCallback) {
handleUsernameTokenPrincipal((UsernameTokenPrincipalCallback) callback);
}
else {
throw new UnsupportedCallbackException(callback);
}
}
/**
* Invoked when the callback has a {@link WSPasswordCallback#DECRYPT} usage.
*
* <p>This method is invoked when WSS4J needs a password to get the private key of the {@link
* WSPasswordCallback#getIdentifier() 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).
*
* <p>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.
*
* <p>This method is invoked when WSS4J needs the password to fill in or to verify a UsernameToken.
*
* <p>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.
*
* <p>This method is invoked when WSS4J needs the password to get the private key of the {@link
* WSPasswordCallback#getIdentifier() 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.
*
* <p>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#SECURITY_CONTEXT_TOKEN} usage.
*
* <p>This method is invoked when WSS4J needs the key to to be associated with a SecurityContextToken.
*
* <p>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.
*
* <p>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#SECRET_KEY} usage.
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
throw new UnsupportedCallbackException(callback);
}
/**
* Invoked when a {@link CleanupCallback} is passed to {@link #handle(Callback[])}.
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleCleanup(CleanupCallback callback) throws IOException, UnsupportedCallbackException {
throw new UnsupportedCallbackException(callback);
}
/**
* Invoked when a {@link UsernameTokenPrincipalCallback} is passed to {@link #handle(Callback[])}.
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleUsernameTokenPrincipal(UsernameTokenPrincipalCallback callback)
throws IOException, UnsupportedCallbackException {
throw new UnsupportedCallbackException(callback);
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright 2005-2014 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.wss4j2.callback;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.Key;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.ws.soap.security.support.KeyStoreUtils;
/**
* Callback handler that uses Java Security {@code KeyStore}s to handle cryptographic callbacks. Allows for
* specific key stores to be set for various cryptographic operations.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @see org.springframework.ws.soap.security.support.KeyStoreFactoryBean
* @since 2.3.0
*/
public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler implements InitializingBean {
private String privateKeyPassword;
private char[] symmetricKeyPassword;
private KeyStore keyStore;
/**
* Invoked when the callback has a {@link WSPasswordCallback#DECRYPT} usage.
*
* <p>This method is invoked when WSS4J needs a password to get the private key of the {@link
* WSPasswordCallback#getIdentifier() 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).
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleDecrypt(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
callback.setPassword(privateKeyPassword);
}
/**
* Invoked when the callback has a {@link WSPasswordCallback#SECRET_KEY} usage.
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
String id = callback.getIdentifier();
Key key;
try {
key = keyStore.getKey(id, symmetricKeyPassword != null ? symmetricKeyPassword : privateKeyPassword.toCharArray());
} catch (UnrecoverableKeyException e) {
throw new IOException("Could not get key", e);
} catch (KeyStoreException e) {
throw new IOException("Could not get key", e);
} catch (NoSuchAlgorithmException e) {
throw new IOException("Could not get key", e);
}
callback.setKey(key.getEncoded());
}
/** 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 decryption 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 defaults to
* the private key password.
*
* @see #setPrivateKeyPassword(String)
*/
public void setSymmetricKeyPassword(String symmetricKeyPassword) {
if (symmetricKeyPassword != null) {
this.symmetricKeyPassword = symmetricKeyPassword.toCharArray();
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (keyStore == null) {
loadDefaultKeyStore();
}
if (symmetricKeyPassword == null) {
symmetricKeyPassword = privateKeyPassword.toCharArray();
}
}
/** 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);
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2005-2014 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.wss4j2.callback;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* Simple callback handler that validates passwords against a in-memory {@code Properties} object. Password
* validation is done on a case-sensitive basis.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @see #setUsers(java.util.Properties)
* @since 2.3.0
*/
public class SimplePasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler
implements InitializingBean {
private Map<String, String> users = new HashMap<String, String>();
/** Sets the users to validate against. Property names are usernames, property values are passwords. */
public void setUsers(Properties users) {
for (Map.Entry<Object, Object> entry : users.entrySet()) {
if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
this.users.put((String) entry.getKey(), (String) entry.getValue());
}
}
}
public void setUsersMap(Map<String, String> users) {
this.users = users;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(users, "users is required");
}
@Override
public void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException
{
String username = callback.getIdentifier();
String passwd = users.get(username);
callback.setPassword(passwd);
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2005-2014 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.wss4j2.callback;
import java.io.IOException;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.cache.NullUserCache;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.CleanupCallback;
/**
* Callback handler that validates a plain text or digest password using an Spring Security {@code UserDetailsService}.
*
* <p>An Spring Security {@link UserDetailsService} is used to load {@link UserDetails} from. The digest of the
* password contained in this details object is then compared with the digest in the message.
*
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @since 2.3.0
*/
public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler
implements InitializingBean {
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 Spring Security user details service. Required. */
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(userDetailsService, "userDetailsService is required");
}
/**
* Invoked when the callback has a {@link WSPasswordCallback#USERNAME_TOKEN} usage.
*
* <p>This method is invoked when WSS4J needs the password to fill in or to verify a UsernameToken.
*
* <p>Default implementation throws an {@link UnsupportedCallbackException}.
*/
protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
UserDetails details = loadUserDetails(callback.getIdentifier());
callback.setPassword(details.getPassword());
}
@Override
protected void handleUsernameTokenPrincipal(UsernameTokenPrincipalCallback callback)
throws IOException, UnsupportedCallbackException {
UserDetails user = loadUserDetails(callback.getPrincipal().getName());
WSUsernameTokenPrincipalImpl principal = callback.getPrincipal();
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), user.getAuthorities());
if (logger.isDebugEnabled()) {
logger.debug("Authentication success: " + authRequest.toString());
}
SecurityContextHolder.getContext().setAuthentication(authRequest);
}
@Override
protected void handleCleanup(CleanupCallback callback) throws IOException, UnsupportedCallbackException {
SecurityContextHolder.clearContext();
}
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;
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.wss4j2.callback;
import java.io.Serializable;
import javax.security.auth.callback.Callback;
import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl;
/**
* Underlying security services instantiate and pass a {@code UsernameTokenPrincipalCallback} to the
* {@code handle} method of a {@code CallbackHandler} to pass a security
* {@code WSUsernameTokenPrincipal}.
*
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @see WSUsernameTokenPrincipalImpl
* @since 2.3.0
*/
public class UsernameTokenPrincipalCallback implements Callback, Serializable {
private static final long serialVersionUID = -3022202225157082715L;
private final WSUsernameTokenPrincipalImpl principal;
/** Construct a {@code UsernameTokenPrincipalCallback}. */
public UsernameTokenPrincipalCallback(WSUsernameTokenPrincipalImpl principal) {
this.principal = principal;
}
/** Get the retrieved {@code Principal}. */
public WSUsernameTokenPrincipalImpl getPrincipal() {
return principal;
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains <code>CallbackHandler</code> implementations for WSS4J 2.0.
</body>
</html>

View File

@@ -0,0 +1,6 @@
<html>
<body>
Contains classes for using the <a href="http://ws.apache.org/wss4j/">Apache WSS4J 2.0</a> WS-Security implementation within
Spring-WS.
</body>
</html>

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2005-2014 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.wss4j2.support;
import java.io.IOException;
import java.util.Properties;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.crypto.Merlin;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
/**
* Spring factory bean for a WSS4J {@link Crypto}. Allows for strong-typed property configuration, or configuration
* through {@link Properties}.
*
* <p>Requires either individual properties, or the {@link #setConfiguration(java.util.Properties) configuration} property
* to be set.
*
* @author Tareq Abed Rabbo
* @author Arjen Poutsma
* @author Jamin Hitchcock
* @see org.apache.ws.security.components.crypto.Crypto
* @since 2.3.0
*/
public class CryptoFactoryBean implements FactoryBean<Crypto>, InitializingBean {
private Properties configuration = new Properties();
private Crypto crypto;
private static final String CRYPTO_PROVIDER_PROPERTY = "org.apache.wss4j.crypto.provider";
/**
* Sets the configuration of the Crypto. Setting this property overrides all previously set configuration, through
* the type-safe properties
*
* @see org.apache.ws.security.components.crypto.CryptoFactory#getInstance(java.util.Properties)
*/
public void setConfiguration(Properties properties) {
Assert.notNull(properties, "'properties' must not be null");
this.configuration.putAll(properties);
}
/**
* Sets the {@link org.apache.ws.security.components.crypto.Crypto} provider name. Defaults to {@link
* org.apache.ws.security.components.crypto.Merlin}.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.provider} property.
*
* @param cryptoProviderClass the crypto provider class
*/
public void setCryptoProvider(Class<? extends Crypto> cryptoProviderClass) {
this.configuration.setProperty(CRYPTO_PROVIDER_PROPERTY, cryptoProviderClass.getName());
}
/**
* Sets the location of the key store to be loaded in the {@link org.apache.ws.security.components.crypto.Crypto}
* instance.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.file} property.
*
* @param location the key store location
* @throws java.io.IOException when the resource cannot be opened
*/
public void setKeyStoreLocation(Resource location) throws IOException {
String resourcePath = getResourcePath(location);
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.file", resourcePath);
}
private String getResourcePath(Resource resource) throws IOException {
try {
return resource.getFile().getAbsolutePath();
}
catch (IOException ex) {
if (resource instanceof ClassPathResource) {
ClassPathResource classPathResource = (ClassPathResource) resource;
return classPathResource.getPath();
}
else {
throw ex;
}
}
}
/**
* Sets the key store provider.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.provider} property.
*
* @param provider the key store provider
*/
public void setKeyStoreProvider(String provider) {
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.provider", provider);
}
/**
* Sets the key store password. Defaults to {@code security}.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.password} property.
*
* @param password the key store password
*/
public void setKeyStorePassword(String password) {
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", password);
}
/**
* Sets the key store type. Defaults to {@link java.security.KeyStore#getDefaultType()}.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.type} property.
*
* @param type the key store type
*/
public void setKeyStoreType(String type) {
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", type);
}
/**
* Sets the trust store password. Defaults to {@code changeit}.
*
* <p>WSS4J crypto uses the standard J2SE trust store, i.e. {@code $JAVA_HOME/lib/security/cacerts}.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.cacerts.password} property.
*
* @param password the trust store password
*/
public void setTrustStorePassword(String password) {
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.cacerts.password", password);
}
/**
* Sets the alias name of the default certificate which has been specified as a property. This should be the
* certificate that is used for signature and encryption. This alias corresponds to the certificate that should be
* used whenever KeyInfo is not present in a signed or an encrypted message.
*
* <p>This property maps to the WSS4J {@code org.apache.ws.security.crypto.merlin.keystore.alias} property.
*
* @param defaultX509Alias alias name of the default X509 certificate
*/
public void setDefaultX509Alias(String defaultX509Alias) {
this.configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", defaultX509Alias);
}
@Override
public void afterPropertiesSet() throws Exception {
if (!configuration.containsKey(CRYPTO_PROVIDER_PROPERTY)) {
configuration.setProperty(CRYPTO_PROVIDER_PROPERTY, Merlin.class.getName());
}
this.crypto = CryptoFactory.getInstance(configuration);
}
@Override
public Class<Crypto> getObjectType() {
return Crypto.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public Crypto getObject() throws Exception {
return crypto;
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains support classes for working with WSS4J 2.0.
</body>
</html>

View File

@@ -146,6 +146,9 @@ public abstract class Wss4jMessageInterceptorUsernameTokenTestCase extends Wss4j
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
}
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.setBspCompliant(false);
interceptor.afterPropertiesSet();
return interceptor;
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jInterceptorTest extends Wss4jInterceptorTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorEncryptionTest extends Wss4jMessageInterceptorEncryptionTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorHeaderTest extends Wss4jMessageInterceptorHeaderTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptorSignTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorSoapActionTest extends Wss4jMessageInterceptorSoapActionTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorSpringSecurityCallbackHandlerTest
extends Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorTimestampTest extends Wss4jMessageInterceptorTimestampTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorUsernameTokenSignatureTest
extends Wss4jMessageInterceptorUsernameTokenSignatureTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class AxiomWss4jMessageInterceptorUsernameTokenTest extends Wss4jMessageInterceptorUsernameTokenTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
/** @author tareq */
public class AxiomWss4jMessageInterceptorX509Test extends Wss4jMessageInterceptorX509TestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jInterceptorTest extends Wss4jInterceptorTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorEncryptionTest extends Wss4jMessageInterceptorEncryptionTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorHeaderTest extends Wss4jMessageInterceptorHeaderTestCase {
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2005-2010 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.wss4j2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.xml.transform.StringSource;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class SaajWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptorSignTestCase {
private static final String PAYLOAD =
"<tru:StockSymbol xmlns:tru=\"http://fabrikam123.com/payloads\">QQQ</tru:StockSymbol>";
@Test
public void testSignAndValidate() throws Exception {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
interceptor.setSecurementActions("Signature");
interceptor.setEnableSignatureConfirmation(false);
interceptor.setSecurementPassword("123456");
interceptor.setSecurementUsername("rsaKey");
SOAPMessage saajMessage = saajSoap11MessageFactory.createMessage();
transformer.transform(new StringSource(PAYLOAD), new DOMResult(saajMessage.getSOAPBody()));
SoapMessage message = new SaajSoapMessage(saajMessage, saajSoap11MessageFactory);
MessageContext messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory));
interceptor.secureMessage(message, messageContext);
SOAPHeader header = ((SaajSoapMessage) message).getSaajMessage().getSOAPHeader();
Iterator<?> iterator = header.getChildElements(new QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security"));
assertTrue("No security header", iterator.hasNext());
SOAPHeaderElement securityHeader = (SOAPHeaderElement) iterator.next();
iterator = securityHeader.getChildElements(new QName("http://www.w3.org/2000/09/xmldsig#", "Signature"));
assertTrue("No signature header", iterator.hasNext());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
message.writeTo(bos);
MimeHeaders mimeHeaders = new MimeHeaders();
mimeHeaders.addHeader("Content-Type", "text/xml");
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
SOAPMessage signed = saajSoap11MessageFactory.createMessage(mimeHeaders, bis);
message = new SaajSoapMessage(signed, saajSoap11MessageFactory);
messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory));
interceptor.validateMessage(message, messageContext);
}
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorSoapActionTest extends Wss4jMessageInterceptorSoapActionTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorSpringSecurityCallbackHandlerTest
extends Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorTimestampTest extends Wss4jMessageInterceptorTimestampTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorUsernameTokenSignatureTest
extends Wss4jMessageInterceptorUsernameTokenSignatureTestCase {
}

View File

@@ -0,0 +1,21 @@
/*
* 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.wss4j2;
public class SaajWss4jMessageInterceptorUsernameTokenTest extends Wss4jMessageInterceptorUsernameTokenTestCase {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.wss4j2;
/** @author tareq */
public class SaajWss4jMessageInterceptorX509Test extends Wss4jMessageInterceptorX509TestCase {
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2005-2010 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.wss4j2;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.WsSecuritySecurementException;
import org.springframework.ws.soap.security.WsSecurityValidationException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public abstract class Wss4jInterceptorTestCase extends Wss4jTestCase {
@Test
public void testHandleRequest() throws Exception {
SoapMessage request = loadSoap11Message("empty-soap.xml");
final Object requestMessage = getMessage(request);
SoapMessage validatedRequest = loadSoap11Message("empty-soap.xml");
final Object validatedRequestMessage = getMessage(validatedRequest);
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor() {
@Override
protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecuritySecurementException {
fail("secure not expected");
}
@Override
protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecurityValidationException {
assertEquals("Invalid message", requestMessage, getMessage(soapMessage));
setMessage(soapMessage, validatedRequestMessage);
}
};
MessageContext context = new DefaultMessageContext(request, getSoap11MessageFactory());
interceptor.handleRequest(context, null);
assertEquals("Invalid request", validatedRequestMessage, getMessage((SoapMessage) context.getRequest()));
}
@Test
public void testHandleResponse() throws Exception {
SoapMessage securedResponse = loadSoap11Message("empty-soap.xml");
final Object securedResponseMessage = getMessage(securedResponse);
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor() {
@Override
protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecuritySecurementException {
setMessage(soapMessage, securedResponseMessage);
}
@Override
protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecurityValidationException {
fail("validate not expected");
}
};
SoapMessage request = loadSoap11Message("empty-soap.xml");
MessageContext context = new DefaultMessageContext(request, getSoap11MessageFactory());
context.getResponse();
interceptor.handleResponse(context, null);
assertEquals("Invalid response", securedResponseMessage, getMessage((SoapMessage) context.getResponse()));
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2005-2014 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.wss4j2;
import java.util.Properties;
import org.junit.Test;
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.wss4j2.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
public abstract class Wss4jMessageInterceptorEncryptionTestCase extends Wss4jTestCase {
protected Wss4jSecurityInterceptor interceptor;
@Override
protected void onSetup() throws Exception {
interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("Encrypt");
interceptor.setSecurementActions("Encrypt");
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("123456");
interceptor.setValidationCallbackHandler(callbackHandler);
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
Properties cryptoFactoryBeanConfig = new Properties();
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks");
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456");
// from the class path
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks");
cryptoFactoryBean.setConfiguration(cryptoFactoryBeanConfig);
cryptoFactoryBean.afterPropertiesSet();
interceptor.setValidationDecryptionCrypto(cryptoFactoryBean
.getObject());
interceptor.setSecurementEncryptionCrypto(cryptoFactoryBean
.getObject());
interceptor.afterPropertiesSet();
}
@Test
public void testDecryptRequest() throws Exception {
SoapMessage message = loadSoap11Message("encrypted-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
Document document = getDocument((SoapMessage) messageContext.getRequest());
assertXpathEvaluatesTo("Decryption error", "Hello", "/SOAP-ENV:Envelope/SOAP-ENV:Body/echo:echoRequest/text()",
document);
assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security",
getDocument(message));
}
@Test
public void testEncryptResponse() throws Exception {
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.setSecurementEncryptionUser("rsakey");
interceptor.secureMessage(message, messageContext);
Document document = getDocument(message);
assertXpathExists("Encryption error", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/xenc:EncryptedKey",
document);
}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright 2005-2010 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.wss4j2;
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import java.util.Properties;
import javax.xml.namespace.QName;
import org.junit.Test;
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.WsSecurityValidationException;
import org.springframework.ws.soap.security.wss4j2.callback.SimplePasswordValidationCallbackHandler;
/**
* @author Arjen Poutsma
* @author Tareq Abedrabbo
* @author Greg Turnquist
*/
public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCase {
private Wss4jSecurityInterceptor interceptor;
private Wss4jSecurityInterceptor interceptorThatKeepsSecurityHeader;
@Override
protected void onSetup() throws Exception {
Properties users = new Properties();
users.setProperty("Bert", "Ernie");
interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidateRequest(true);
interceptor.setSecureResponse(true);
interceptor.setValidationActions("UsernameToken");
SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
callbackHandler.setUsers(users);
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.afterPropertiesSet();
interceptorThatKeepsSecurityHeader = new Wss4jSecurityInterceptor();
interceptorThatKeepsSecurityHeader.setValidateRequest(true);
interceptorThatKeepsSecurityHeader.setSecureResponse(true);
interceptorThatKeepsSecurityHeader.setValidationActions("UsernameToken");
interceptorThatKeepsSecurityHeader.setValidationCallbackHandler(callbackHandler);
interceptorThatKeepsSecurityHeader.setRemoveSecurityHeader(false);
interceptorThatKeepsSecurityHeader.afterPropertiesSet();
}
@Test
public void testValidateUsernameTokenPlainText() throws Exception {
SoapMessage message = loadSoap11Message("usernameTokenPlainTextWithHeaders-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
Object result = getMessage(message);
assertNotNull("No result returned", result);
for (Iterator<SoapHeaderElement> i = message.getEnvelope().getHeader().examineAllHeaderElements(); i.hasNext();) {
SoapHeaderElement element = i.next();
QName name = element.getName();
if (name.getNamespaceURI()
.equals("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")) {
fail("Security Header not removed");
}
}
assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security",
getDocument(message));
assertXpathExists("header1 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header1", getDocument(message));
assertXpathExists("header2 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header2", getDocument(message));
}
@Test
public void testValidateUsernameTokenPlainTextButKeepSecurityHeader() throws Exception {
SoapMessage message = loadSoap11Message("usernameTokenPlainTextWithHeaders-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptorThatKeepsSecurityHeader.validateMessage(message, messageContext);
Object result = getMessage(message);
assertNotNull("No result returned", result);
boolean foundSecurityHeader = false;
for (Iterator<SoapHeaderElement> i = message.getEnvelope().getHeader().examineAllHeaderElements(); i.hasNext();) {
SoapHeaderElement element = i.next();
QName name = element.getName();
if (name.getNamespaceURI()
.equals("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")) {
foundSecurityHeader = true;
}
}
assertTrue(foundSecurityHeader);
assertXpathExists("header1 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header1", getDocument(message));
assertXpathExists("header2 not found", "/SOAP-ENV:Envelope/SOAP-ENV:Header/header2", getDocument(message));
}
@Test(expected=WsSecurityValidationException.class)
public void testEmptySecurityHeader() throws Exception {
SoapMessage message = loadSoap11Message("emptySecurityHeader-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
}
@Test
public void testPreserveCustomHeaders() throws Exception {
interceptor.setSecurementActions("UsernameToken");
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
ByteArrayOutputStream os = new ByteArrayOutputStream();
SoapMessage message = loadSoap11Message("customHeader-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
message.writeTo(os);
String document = os.toString("UTF-8");
assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1",
document);
assertXpathNotExists("Header 2 exist", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", document);
interceptor.secureMessage(message, messageContext);
SoapHeaderElement element = message.getSoapHeader().addHeaderElement(new QName("http://test", "header2"));
element.setText("test2");
os = new ByteArrayOutputStream();
message.writeTo(os);
document = os.toString("UTF-8");
assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1",
document);
assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2",
document);
os = new ByteArrayOutputStream();
message.writeTo(os);
document = os.toString("UTF-8");
assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1",
document);
assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2",
document);
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2005-2010 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.wss4j2;
import java.util.Properties;
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.wss4j2.support.CryptoFactoryBean;
import org.junit.Test;
import org.w3c.dom.Document;
import static org.junit.Assert.assertNotNull;
public abstract class Wss4jMessageInterceptorSignTestCase extends Wss4jTestCase {
protected Wss4jSecurityInterceptor interceptor;
@Override
protected void onSetup() throws Exception {
interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("Signature");
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
Properties cryptoFactoryBeanConfig = new Properties();
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks");
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456");
// from the class path
cryptoFactoryBeanConfig.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks");
cryptoFactoryBean.setConfiguration(cryptoFactoryBeanConfig);
cryptoFactoryBean.afterPropertiesSet();
interceptor.setValidationSignatureCrypto(cryptoFactoryBean
.getObject());
interceptor.setSecurementSignatureCrypto(cryptoFactoryBean
.getObject());
interceptor.afterPropertiesSet();
}
@Test
public void testValidateCertificate() throws Exception {
SoapMessage message = loadSoap11Message("signed-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
Object result = getMessage(message);
assertNotNull("No result returned", result);
assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security",
getDocument(message));
}
@Test
public void testValidateCertificateWithSignatureConfirmation() throws Exception {
SoapMessage message = loadSoap11Message("signed-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.setEnableSignatureConfirmation(true);
interceptor.validateMessage(message, messageContext);
WebServiceMessage response = messageContext.getResponse();
interceptor.secureMessage(message, messageContext);
assertNotNull("No result returned", response);
Document document = getDocument((SoapMessage) response);
assertXpathExists("Absent SignatureConfirmation element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse11:SignatureConfirmation", document);
}
@Test
public void testSignResponse() throws Exception {
interceptor.setSecurementActions("Signature");
interceptor.setEnableSignatureConfirmation(false);
interceptor.setSecurementPassword("123456");
interceptor.setSecurementUsername("rsaKey");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
// interceptor.setSecurementSignatureKeyIdentifier("IssuerSerial");
interceptor.secureMessage(message, messageContext);
Document document = getDocument(message);
assertXpathExists("Absent SignatureConfirmation element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature", document);
}
@Test
public void testSignResponseWithSignatureUser() throws Exception {
interceptor.setSecurementActions("Signature");
interceptor.setEnableSignatureConfirmation(false);
interceptor.setSecurementPassword("123456");
interceptor.setSecurementSignatureUser("rsaKey");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.secureMessage(message, messageContext);
Document document = getDocument(message);
assertXpathExists("Absent SignatureConfirmation element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature", document);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2005-2010 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.wss4j2;
import java.util.Properties;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.wss4j2.callback.SimplePasswordValidationCallbackHandler;
import org.apache.wss4j.dom.WSConstants;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public abstract class Wss4jMessageInterceptorSoapActionTestCase extends Wss4jTestCase {
private static final String SOAP_ACTION = "\"http://test\"";
private Properties users;
private Wss4jSecurityInterceptor interceptor;
@Override
protected void onSetup() throws Exception {
users = new Properties();
users.setProperty("Bert", "Ernie");
interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("UsernameToken");
interceptor.setSecurementActions("UsernameToken");
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
callbackHandler.setUsers(users);
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.afterPropertiesSet();
}
@Test
public void testPreserveSoapActionOnValidation() throws Exception {
SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml");
message.setSoapAction(SOAP_ACTION);
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
assertNotNull("Soap Action must not be null", message.getSoapAction());
assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction());
}
@Test
public void testPreserveSoap12ActionOnValidation() throws Exception {
SoapMessage message = loadSoap12Message("usernameTokenPlainText-soap12.xml");
message.setSoapAction(SOAP_ACTION);
WebServiceMessageFactory messageFactory = getSoap12MessageFactory();
MessageContext messageContext = new DefaultMessageContext(message, messageFactory);
interceptor.validateMessage(message, messageContext);
assertNotNull("Soap Action must not be null", message.getSoapAction());
assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction());
}
@Test
public void testPreserveSoapActionOnSecurement() throws Exception {
SoapMessage message = loadSoap11Message("empty-soap.xml");
message.setSoapAction(SOAP_ACTION);
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.secureMessage(message, messageContext);
assertNotNull("Soap Action must not be null", message.getSoapAction());
assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction());
}
@Test
public void testPreserveSoap12ActionOnSecurement() throws Exception {
SoapMessage message = loadSoap12Message("empty-soap12.xml");
message.setSoapAction(SOAP_ACTION);
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
MessageContext messageContext = getSoap12MessageContext(message);
interceptor.secureMessage(message, messageContext);
assertNotNull("Soap Action must not be null", message.getSoapAction());
assertEquals("Soap Action is different from expected", SOAP_ACTION, message.getSoapAction());
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright 2005-2012 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.wss4j2;
import java.util.Properties;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
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.wss4j2.callback.SpringSecurityPasswordValidationCallbackHandler;
import org.apache.wss4j.dom.WSConstants;
import org.junit.After;
import org.junit.Test;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase extends Wss4jTestCase {
private Properties users = new Properties();
private AuthenticationManager authenticationManager;
@Override
protected void onSetup() throws Exception {
authenticationManager = createMock(AuthenticationManager.class);
users.setProperty("Bert", "Ernie,ROLE_TEST");
}
@After
public void tearDown() throws Exception {
verify(authenticationManager);
SecurityContextHolder.clearContext();
}
@Test
public void testValidateUsernameTokenPlainText() throws Exception {
EndpointInterceptor interceptor = prepareInterceptor("UsernameToken", true, false);
SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.handleRequest(messageContext, null);
assertValidateUsernameToken(message);
// test clean up
messageContext.getResponse();
interceptor.handleResponse(messageContext, null);
interceptor.afterCompletion(messageContext, null, null);
assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
@Test
public void testValidateUsernameTokenDigest() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("UsernameToken");
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.handleRequest(messageContext);
interceptor = prepareInterceptor("UsernameToken", true, true);
interceptor.handleRequest(messageContext, null);
assertValidateUsernameToken(message);
// test clean up
messageContext.getResponse();
interceptor.handleResponse(messageContext, null);
interceptor.afterCompletion(messageContext, null, null);
assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
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));
assertNotNull("No Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
protected Wss4jSecurityInterceptor prepareInterceptor(String actions, boolean validating, boolean digest)
throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
if (validating) {
interceptor.setValidationActions(actions);
}
else {
interceptor.setSecurementActions(actions);
}
SpringSecurityPasswordValidationCallbackHandler callbackHandler =
new SpringSecurityPasswordValidationCallbackHandler();
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(users);
callbackHandler.setUserDetailsService(userDetailsManager);
if (digest) {
interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
}
else {
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
}
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.afterPropertiesSet();
replay(authenticationManager);
return interceptor;
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2005-2010 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.wss4j2;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.WsSecurityValidationException;
import org.junit.Test;
import org.w3c.dom.Document;
import static org.junit.Assert.assertEquals;
public abstract class Wss4jMessageInterceptorTimestampTestCase extends Wss4jTestCase {
@Test
public void testAddTimestamp() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("Timestamp");
interceptor.afterPropertiesSet();
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext context = getSoap11MessageContext(message);
interceptor.secureMessage(message, context);
Document document = getDocument(message);
assertXpathExists("timestamp header not found",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp", document);
}
@Test
public void testValidateTimestamp() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("Timestamp");
interceptor.afterPropertiesSet();
SoapMessage message = getMessageWithTimestamp();
MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, context);
assertXpathNotExists("Security Header not removed", "/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security",
getDocument(message));
}
@Test(expected = WsSecurityValidationException.class)
public void testValidateTimestampWithExpiredTtl() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setValidationActions("Timestamp");
interceptor.afterPropertiesSet();
SoapMessage message = loadSoap11Message("expiredTimestamp-soap.xml");
MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, context);
}
@Test
public void testSecureTimestampWithCustomTtl() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("Timestamp");
interceptor.setTimestampStrict(true);
int ttlInSeconds = 1;
interceptor.setSecurementTimeToLive(ttlInSeconds);
interceptor.afterPropertiesSet();
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext context = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.secureMessage(message, context);
String created = xpathTemplate.evaluateAsString("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp/wsu:Created/text()",
message.getEnvelope().getSource());
String expires = xpathTemplate.evaluateAsString("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsu:Timestamp/wsu:Expires/text()",
message.getEnvelope().getSource());
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS'Z'");
long actualTtl = format.parse(expires).getTime() - format.parse(created).getTime();
assertEquals("invalid ttl", 1000 * ttlInSeconds, actualTtl);
}
private SoapMessage getMessageWithTimestamp() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("Timestamp");
interceptor.afterPropertiesSet();
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext context = getSoap11MessageContext(message);
interceptor.secureMessage(message, context);
return message;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2005-2010 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.wss4j2;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.junit.Test;
import org.w3c.dom.Document;
public abstract class Wss4jMessageInterceptorUsernameTokenSignatureTestCase extends Wss4jTestCase {
@Test
public void testAddUsernameTokenSignature() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("UsernameToken");
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
interceptor.afterPropertiesSet();
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext context = getSoap11MessageContext(message);
interceptor.secureMessage(message, context);
Document doc = getDocument(message);
assertXpathEvaluatesTo("Invalid Username", "Bert",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc);
assertXpathExists("Invalid Password",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest']/text()",
doc);
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright 2005-2010 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.wss4j2;
import static org.junit.Assert.assertNotNull;
import java.util.Properties;
import org.apache.wss4j.dom.WSConstants;
import org.junit.Test;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.wss4j2.callback.SimplePasswordValidationCallbackHandler;
import org.w3c.dom.Document;
public abstract class Wss4jMessageInterceptorUsernameTokenTestCase extends Wss4jTestCase {
private Properties users = new Properties();
@Override
protected void onSetup() throws Exception {
users.setProperty("Bert", "Ernie");
}
@Test
public void testValidateUsernameTokenPlainText() throws Exception {
Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", true, false);
SoapMessage message = loadSoap11Message("usernameTokenPlainText-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
assertValidateUsernameToken(message);
}
@Test
public void testValidateUsernameTokenDigest() throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("UsernameToken");
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.handleRequest(messageContext);
interceptor = prepareInterceptor("UsernameToken", true, true);
interceptor.validateMessage(message, messageContext);
assertValidateUsernameToken(message);
}
@Test
public void testValidateUsernameTokenWithQualifiedType() throws Exception {
Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", true, false);
SoapMessage message = loadSoap11Message("usernameTokenPlainTextQualifiedType-soap.xml");
MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory());
interceptor.validateMessage(message, messageContext);
assertValidateUsernameToken(message);
}
@Test
public void testAddUsernameTokenPlainText() throws Exception {
Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", false, false);
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.secureMessage(message, messageContext);
assertAddUsernameTokenPlainText(message);
}
@Test
public void testAddUsernameTokenDigest() throws Exception {
Wss4jSecurityInterceptor interceptor = prepareInterceptor("UsernameToken", false, true);
interceptor.setSecurementUsername("Bert");
interceptor.setSecurementPassword("Ernie");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.secureMessage(message, messageContext);
assertAddUsernameTokenDigest(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));
}
protected void assertAddUsernameTokenPlainText(SoapMessage message) throws Exception {
Object result = getMessage(message);
assertNotNull("No result returned", result);
Document doc = getDocument(message);
assertXpathEvaluatesTo("Invalid Username", "Bert",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc);
assertXpathEvaluatesTo("Invalid Password", "Ernie",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText']/text()",
doc);
}
protected void assertAddUsernameTokenDigest(SoapMessage message) throws Exception {
Object result = getMessage(message);
Document doc = getDocument(message);
assertNotNull("No result returned", result);
assertXpathEvaluatesTo("Invalid Username", "Bert",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Username/text()", doc);
assertXpathExists("Password does not exist",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:UsernameToken/wsse:Password[@Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest']",
doc);
}
protected Wss4jSecurityInterceptor prepareInterceptor(String actions, boolean validating, boolean digest)
throws Exception {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
if (validating) {
interceptor.setValidationActions(actions);
}
else {
interceptor.setSecurementActions(actions);
}
SimplePasswordValidationCallbackHandler callbackHandler = new SimplePasswordValidationCallbackHandler();
callbackHandler.setUsers(users);
if (digest) {
interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST);
}
else {
interceptor.setSecurementPasswordType(WSConstants.PW_TEXT);
}
interceptor.setValidationCallbackHandler(callbackHandler);
interceptor.setBspCompliant(false);
interceptor.afterPropertiesSet();
return interceptor;
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2005-2014 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.wss4j2;
import org.apache.wss4j.common.crypto.Merlin;
import org.junit.Test;
import org.w3c.dom.Document;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
public abstract class Wss4jMessageInterceptorX509TestCase extends Wss4jTestCase {
protected Wss4jSecurityInterceptor interceptor;
@Override
protected void onSetup() throws Exception {
interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementActions("Signature");
interceptor.setValidationActions("Signature");
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setCryptoProvider(Merlin.class);
cryptoFactoryBean.setKeyStoreType("jceks");
cryptoFactoryBean.setKeyStorePassword("123456");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("private.jks"));
cryptoFactoryBean.afterPropertiesSet();
interceptor.setSecurementSignatureCrypto(cryptoFactoryBean
.getObject());
interceptor.setValidationSignatureCrypto(cryptoFactoryBean
.getObject());
interceptor.afterPropertiesSet();
}
@Test
public void testAddCertificate() throws Exception {
interceptor.setSecurementPassword("123456");
interceptor.setSecurementUsername("rsaKey");
SoapMessage message = loadSoap11Message("empty-soap.xml");
MessageContext messageContext = getSoap11MessageContext(message);
interceptor.setSecurementSignatureKeyIdentifier("DirectReference");
interceptor.secureMessage(message, messageContext);
Document document = getDocument(message);
assertXpathExists("Absent BinarySecurityToken element",
"/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/wsse:BinarySecurityToken", document);
// lets verify the signature that we've just generated
interceptor.validateMessage(message, messageContext);
}
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright 2005-2010 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.wss4j2;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.dom.DOMSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
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.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.axiom.AxiomSoapMessage;
import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;
import org.springframework.ws.soap.axiom.support.AxiomUtils;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.xml.transform.StringSource;
import org.springframework.xml.xpath.Jaxp13XPathTemplate;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.junit.Assert;
import org.junit.Before;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import static org.junit.Assert.assertTrue;
public abstract class Wss4jTestCase {
protected MessageFactory saajSoap11MessageFactory;
protected MessageFactory saajSoap12MessageFactory;
protected final boolean axiomTest = this.getClass().getSimpleName().startsWith("Axiom");
protected final boolean saajTest = this.getClass().getSimpleName().startsWith("Saaj");
protected Jaxp13XPathTemplate xpathTemplate = new Jaxp13XPathTemplate();
@Before
public final void setUp() throws Exception {
if (!axiomTest && !saajTest) {
throw new IllegalArgumentException("test class name must start with either Axiom or Saaj");
}
saajSoap11MessageFactory = MessageFactory.newInstance();
saajSoap12MessageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
Map<String, String> namespaces = new HashMap<String, String>();
namespaces.put("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
namespaces.put("wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#");
namespaces.put("xenc", "http://www.w3.org/2001/04/xmlenc#");
namespaces.put("wsse11", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd");
namespaces.put("echo", "http://www.springframework.org/spring-ws/samples/echo");
namespaces.put("wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
namespaces.put("test", "http://test");
xpathTemplate.setNamespaces(namespaces);
onSetup();
}
protected void assertXpathEvaluatesTo(String message,
String expectedValue,
String xpathExpression,
Document document) {
String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new DOMSource(document));
Assert.assertEquals(message, expectedValue, actualValue);
}
protected void assertXpathEvaluatesTo(String message,
String expectedValue,
String xpathExpression,
String document) {
String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new StringSource(document));
Assert.assertEquals(message, expectedValue, actualValue);
}
protected void assertXpathExists(String message, String xpathExpression, Document document) {
Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document));
Assert.assertNotNull(message, node);
}
protected void assertXpathNotExists(String message, String xpathExpression, Document document) {
Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document));
Assert.assertNull(message, node);
}
protected void assertXpathNotExists(String message, String xpathExpression, String document) {
Node node = xpathTemplate.evaluateAsNode(xpathExpression, new StringSource(document));
Assert.assertNull(message, node);
}
protected SaajSoapMessage loadSaaj11Message(String fileName) throws Exception {
MimeHeaders mimeHeaders = new MimeHeaders();
mimeHeaders.addHeader("Content-Type", "text/xml");
Resource resource = new ClassPathResource(fileName, getClass());
InputStream is = resource.getInputStream();
try {
assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists());
is = resource.getInputStream();
return new SaajSoapMessage(saajSoap11MessageFactory.createMessage(mimeHeaders, is), saajSoap11MessageFactory);
}
finally {
is.close();
}
}
protected SaajSoapMessage loadSaaj12Message(String fileName) throws Exception {
MimeHeaders mimeHeaders = new MimeHeaders();
mimeHeaders.addHeader("Content-Type", "application/soap+xml");
Resource resource = new ClassPathResource(fileName, getClass());
InputStream is = resource.getInputStream();
try {
assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists());
is = resource.getInputStream();
return new SaajSoapMessage(saajSoap12MessageFactory.createMessage(mimeHeaders, is), saajSoap12MessageFactory);
}
finally {
is.close();
}
}
protected AxiomSoapMessage loadAxiom11Message(String fileName) throws Exception {
Resource resource = new ClassPathResource(fileName, getClass());
InputStream is = resource.getInputStream();
try {
assertTrue("Could not load Axiom message [" + resource + "]", resource.exists());
is = resource.getInputStream();
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(is);
StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, null);
org.apache.axiom.soap.SOAPMessage soapMessage = builder.getSoapMessage();
return new AxiomSoapMessage(soapMessage, "", true, true);
}
finally {
is.close();
}
}
@SuppressWarnings("Since15")
protected AxiomSoapMessage loadAxiom12Message(String fileName) throws Exception {
Resource resource = new ClassPathResource(fileName, getClass());
InputStream is = resource.getInputStream();
try {
assertTrue("Could not load Axiom message [" + resource + "]", resource.exists());
is = resource.getInputStream();
XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(is);
StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(parser, SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
org.apache.axiom.soap.SOAPMessage soapMessage = builder.getSoapMessage();
return new AxiomSoapMessage(soapMessage, "", true, true);
}
finally {
is.close();
}
}
protected Object getMessage(SoapMessage soapMessage) {
if (soapMessage instanceof SaajSoapMessage) {
return ((SaajSoapMessage) soapMessage).getSaajMessage();
}
if (soapMessage instanceof AxiomSoapMessage) {
return ((AxiomSoapMessage) soapMessage).getAxiomMessage();
}
throw new IllegalArgumentException("Illegal message: " + soapMessage);
}
protected void setMessage(SoapMessage soapMessage, Object message) {
if (soapMessage instanceof SaajSoapMessage) {
((SaajSoapMessage) soapMessage).setSaajMessage((SOAPMessage) message);
return;
}
if (soapMessage instanceof AxiomSoapMessage) {
((AxiomSoapMessage) soapMessage).setAxiomMessage((org.apache.axiom.soap.SOAPMessage) message);
return;
}
throw new IllegalArgumentException("Illegal message: " + message);
}
protected void onSetup() throws Exception {
}
protected SoapMessage loadSoap11Message(String fileName) throws Exception {
if (axiomTest) {
return loadAxiom11Message(fileName);
}
if (saajTest) {
return loadSaaj11Message(fileName);
}
throw new IllegalArgumentException();
}
protected SoapMessage loadSoap12Message(String fileName) throws Exception {
if (axiomTest) {
return loadAxiom12Message(fileName);
}
if (saajTest) {
return loadSaaj12Message(fileName);
}
throw new IllegalArgumentException();
}
protected SoapMessageFactory getSoap11MessageFactory() throws Exception {
if (axiomTest) {
return new AxiomSoapMessageFactory();
}
if (saajTest) {
return new SaajSoapMessageFactory(saajSoap11MessageFactory);
}
throw new IllegalArgumentException();
}
protected SoapMessageFactory getSoap12MessageFactory() throws Exception {
SoapMessageFactory messageFactory;
if (axiomTest) {
messageFactory = new AxiomSoapMessageFactory();
} else if (saajTest) {
messageFactory = new SaajSoapMessageFactory(saajSoap12MessageFactory);
} else
throw new IllegalArgumentException();
messageFactory.setSoapVersion(SoapVersion.SOAP_12);
return messageFactory;
}
protected Document getDocument(SoapMessage message) throws Exception {
if (axiomTest) {
return AxiomUtils.toDocument(((AxiomSoapMessage) message).getAxiomMessage().getSOAPEnvelope());
}
if (saajTest) {
return ((SaajSoapMessage) message).getSaajMessage().getSOAPPart();
}
throw new IllegalArgumentException();
}
protected MessageContext getSoap11MessageContext(final SoapMessage response) throws Exception {
return new DefaultMessageContext(response, getSoap11MessageFactory()) {
@Override
public WebServiceMessage getResponse() {
return response;
}
};
}
protected MessageContext getSoap12MessageContext(final SoapMessage response) throws Exception {
return new DefaultMessageContext(response, getSoap12MessageFactory()) {
@Override
public WebServiceMessage getResponse() {
return response;
}
};
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2005-2012 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.wss4j2.callback;
import java.security.KeyStore;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.soap.security.support.KeyStoreFactoryBean;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class KeyStoreCallbackHandlerTest {
private KeyStoreCallbackHandler callbackHandler;
private WSPasswordCallback callback;
@Before
public void setUp() throws Exception {
callbackHandler = new KeyStoreCallbackHandler();
callback = new WSPasswordCallback("secretkey", WSPasswordCallback.SECRET_KEY);
KeyStoreFactoryBean factory = new KeyStoreFactoryBean();
factory.setLocation(new ClassPathResource("private.jks"));
factory.setPassword("123456");
factory.setType("JCEKS");
factory.afterPropertiesSet();
KeyStore keyStore = factory.getObject();
callbackHandler.setKeyStore(keyStore);
callbackHandler.setSymmetricKeyPassword("123456");
}
@Test
public void testHandleKeyName() throws Exception {
callbackHandler.handleInternal(callback);
Assert.assertNotNull("symmetric key must not be null", callback.getKey());
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2005-2012 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.wss4j2.callback;
import java.util.Collection;
import java.util.Collections;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.apache.wss4j.common.principal.WSUsernameTokenPrincipalImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.easymock.EasyMock.*;
/** @author tareq */
public class SpringSecurityPasswordValidationCallbackHandlerTest {
private SpringSecurityPasswordValidationCallbackHandler callbackHandler;
private SimpleGrantedAuthority grantedAuthority;
private UsernameTokenPrincipalCallback callback;
private UserDetails user;
@Before
public void setUp() throws Exception {
callbackHandler = new SpringSecurityPasswordValidationCallbackHandler();
grantedAuthority = new SimpleGrantedAuthority("ROLE_1");
user = new User("Ernie", "Bert", true, true, true, true, Collections.singleton(grantedAuthority));
WSUsernameTokenPrincipalImpl principal = new WSUsernameTokenPrincipalImpl("Ernie", true);
callback = new UsernameTokenPrincipalCallback(principal);
}
@Test
public void testHandleUsernameTokenPrincipal() throws Exception {
UserDetailsService userDetailsService = createMock(UserDetailsService.class);
callbackHandler.setUserDetailsService(userDetailsService);
expect(userDetailsService.loadUserByUsername("Ernie")).andReturn(user).anyTimes();
replay(userDetailsService);
callbackHandler.handleUsernameTokenPrincipal(callback);
SecurityContext context = SecurityContextHolder.getContext();
Assert.assertNotNull("SecurityContext must not be null", context);
Authentication authentication = context.getAuthentication();
Assert.assertNotNull("Authentication must not be null", authentication);
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
Assert.assertTrue("GrantedAuthority[] must not be null or empty",
(authorities != null && authorities.size() > 0));
Assert.assertEquals("Unexpected authority", grantedAuthority, authorities.iterator().next());
verify(userDetailsService);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2005-2010 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.wss4j2.support;
import java.util.Properties;
import org.apache.wss4j.common.crypto.Merlin;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
public class CryptoFactoryBeanTest {
private CryptoFactoryBean factoryBean;
@Before
public void setUp() throws Exception {
factoryBean = new CryptoFactoryBean();
}
@Test
public void testSetConfiguration() throws Exception {
Properties configuration = new Properties();
configuration.setProperty("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", "jceks");
configuration.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", "123456");
configuration.setProperty("org.apache.ws.security.crypto.merlin.file", "private.jks");
factoryBean.setConfiguration(configuration);
factoryBean.afterPropertiesSet();
Object result = factoryBean.getObject();
Assert.assertNotNull("No result", result);
Assert.assertTrue("Not a Merlin instance", result instanceof Merlin);
}
@Test
public void testProperties() throws Exception {
factoryBean.setKeyStoreType("jceks");
factoryBean.setKeyStorePassword("123456");
factoryBean.setKeyStoreLocation(new ClassPathResource("private.jks"));
factoryBean.afterPropertiesSet();
Object result = factoryBean.getObject();
Assert.assertNotNull("No result", result);
Assert.assertTrue("Not a Merlin instance", result instanceof Merlin);
}
}

View File

@@ -0,0 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<header1 xmlns="http://test">test1</header1>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,6 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<echoResponse xmlns="http://www.springframework.org/spring-ws/samples/echo">Hello</echoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,5 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,5 @@
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</env:Body>
</env:Envelope>

View File

@@ -0,0 +1,10 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1">
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"><SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1"><xenc:EncryptedKey Id="EncKeyId-urn:uuid:8DDF426E79084C559F12042485592464">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"></xenc:EncryptionMethod>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference><ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=Unknown,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown</ds:X509IssuerName>
<ds:X509SerialNumber>1204234455</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data></wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData><xenc:CipherValue>gqgcmkwA9dsfFQNyt8V+ztLMCMy7DZ/DbQ3Yrt3XSh8E9qVBwrZmWV5LUw2qrxpcTCYQK3NK4kuc9IVedAF3PzKiYKOWG/fN01Cpk63vVUox6gqp9N4DZRSkfvxVbuxzUdyrsvn+WUYPKjpHFbQdvSzduydPgrleLBFodl021Lk=</xenc:CipherValue></xenc:CipherData>
<xenc:ReferenceList><xenc:DataReference URI="#EncDataId-1174947815"></xenc:DataReference></xenc:ReferenceList></xenc:EncryptedKey></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body><xenc:EncryptedData Id="EncDataId-1174947815" Type="http://www.w3.org/2001/04/xmlenc#Content"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"></xenc:EncryptionMethod><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:Reference URI="#EncKeyId-urn:uuid:8DDF426E79084C559F12042485592464"></wsse:Reference></wsse:SecurityTokenReference>
</ds:KeyInfo><xenc:CipherData><xenc:CipherValue>HrhKCP62Qn2yxsu4CKsTyNoMxJuXQji6uubgMlYD1j/+kLEfUZwlzWYvu1hHW2nnjZI2LDoMaktE
SUlbafeejM9JJ7LNaTSs0dzzpjhmbm0a8E5i0B+Fth62zHB8L4fZZVYVDqLUn37CQTGASTVJDt94
NJRF/Fk0JPyW32iCRpPvrwaJzw/45mkYMaqPsvvcj7VKr4EoH96d2ilRENZXuIE6MiR+nBmyfdgl
21Mv8q04uwCTWBykDqrk95QG07sXInAsp98rTR6kmU+8ntftEVpTGP9TEMQ+7SaXHXH2U3IqITo0
e5dCizixVlotEn+X</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></SOAP-ENV:Body></SOAP-ENV:Envelope>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-27">
<wsu:Created>2009-12-25T15:43:22.687Z</wsu:Created>
<wsu:Expires>2009-12-25T15:48:22.687Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="Signature-13673945">
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:Reference URI="#id-32487478" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">70oDCsbAmt7qauS7FmUvB7oVDfM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
lUrzlFJIz4SRTf+qP9zPZr0s9tN+Suu+XJ2iwVwSMoJIfw+1YQSnWrQZD7EctacGN8iAHqP5g/LK
mXtOw0Ar03uwjoeUBqmchcIjWZjyYYmvtTDF9VA70z07C4zp7FYAP7GLKVCb4hmFn81mHLhWYlo7
2bQEpkIOjaC5IBoFiLI=
</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-30426707" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-28145575" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerSerial xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509IssuerName xmlns:ds="http://www.w3.org/2000/09/xmldsig#">CN=Unknown,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown</ds:X509IssuerName>
<ds:X509SerialNumber xmlns:ds="http://www.w3.org/2000/09/xmldsig#">1204234455</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data></wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-32487478"><tns:echoRequest xmlns:tns="http://www.springframework.org/spring-ws/samples/echo">Hello</tns:echoRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>

View File

@@ -0,0 +1,6 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" SOAP-ENV:mustUnderstand="1"><wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-1149205720423-1352053129" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:Username>Bert</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">kwNstEaiFOrI7B31j7GuETYvdgk=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">9mdsYDCrjjYRur0rxzYt2oD7</wsse:Nonce><wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2006-06-01T23:48:42Z</wsu:Created></wsse:UsernameToken></wsse:Security></SOAP-ENV:Header><SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,19 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="XWSSGID-1149200055993710197275"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>Bert</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
>Ernie</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,19 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="XWSSGID-1149200055993710197275"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>Bert</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
>Ernie</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,17 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="XWSSGID-1149200055993710197275"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>Bert</wsse:Username>
<wsse:Password wsse:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Ernie</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,21 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<header1>1</header1>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="XWSSGID-1149200055993710197275"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>Bert</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
>Ernie</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<header2>2</header2>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>