Package org.springframework.ws.soap.security.xwss

Source Code of org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor

/*
* 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.xwss;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.soap.SOAPMessage;

import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.XWSSProcessor;
import com.sun.xml.wss.XWSSProcessorFactory;
import com.sun.xml.wss.XWSSecurityException;
import com.sun.xml.wss.impl.WssSoapFaultException;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor;
import org.springframework.ws.soap.security.WsSecurityValidationException;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import org.springframework.ws.soap.security.xwss.callback.XwssCallbackHandlerChain;

/**
* WS-Security endpoint interceptor  that is based on Sun's XML and Web Services Security package (XWSS). This
* WS-Security implementation is part of the Java Web Services Developer Pack (Java WSDP).
*
* <p>This interceptor needs a {@code CallbackHandler} to operate. This handler is used to retrieve certificates,
* private keys, validate user credentials, etc. Refer to the XWSS Javadoc to learn more about the specific
* {@code Callback}s fired by XWSS. You can also set multiple handlers, each of which will be used in turn.
*
* <p>Additionally, you must define a XWSS policy file by setting {@code policyConfiguration} property. The format of
* the policy file is documented in the <a href="http://java.sun.com/webservices/docs/1.6/tutorial/doc/XWS-SecurityIntro4.html#wp529900">Java
* Web Services Tutorial</a>.
*
* <p><b>Note</b> that this interceptor depends on SAAJ, and thus requires {@code SaajSoapMessage}s to operate. This
* means that you must use a {@code SaajSoapMessageFactory} to create the SOAP messages.
*
* @author Arjen Poutsma
* @see #setCallbackHandler(javax.security.auth.callback.CallbackHandler)
* @see #setPolicyConfiguration(org.springframework.core.io.Resource)
* @see com.sun.xml.wss.impl.callback.XWSSCallback
* @see org.springframework.ws.soap.saaj.SaajSoapMessageFactory
* @see <a href="https://xwss.dev.java.net/">XWSS</a>
* @since 1.0.0
*/
public class XwsSecurityInterceptor extends AbstractWsSecurityInterceptor implements InitializingBean {

    private XWSSProcessor processor;

    private CallbackHandler callbackHandler;

    private Resource policyConfiguration;

    /**
     * Sets the handler to resolve XWSS callbacks. Setting either this propery, or {@code callbackHandlers}, is
     * required.
     *
     * @see com.sun.xml.wss.impl.callback.XWSSCallback
     * @see #setCallbackHandlers(javax.security.auth.callback.CallbackHandler[])
     */
    public void setCallbackHandler(CallbackHandler callbackHandler) {
        this.callbackHandler = callbackHandler;
    }

    /**
     * Sets the handlers to resolve XWSS callbacks. Setting either this propery, or {@code callbackHandlers}, is
     * required.
     *
     * @see com.sun.xml.wss.impl.callback.XWSSCallback
     * @see #setCallbackHandler(javax.security.auth.callback.CallbackHandler)
     */
    public void setCallbackHandlers(CallbackHandler[] callbackHandler) {
        this.callbackHandler = new XwssCallbackHandlerChain(callbackHandler);
    }

    /** Sets the policy configuration to use for XWSS. Required. */
    public void setPolicyConfiguration(Resource policyConfiguration) {
        this.policyConfiguration = policyConfiguration;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(policyConfiguration, "policyConfiguration is required");
        Assert.isTrue(policyConfiguration.exists(), "policyConfiguration [" + policyConfiguration + "] does not exist");
        Assert.notNull(callbackHandler, "callbackHandler is required");
        XWSSProcessorFactory processorFactory = XWSSProcessorFactory.newInstance();
        InputStream is = null;
        try {
            if (logger.isInfoEnabled()) {
                logger.info("Loading policy configuration from from '" + policyConfiguration + "'");
            }
            is = policyConfiguration.getInputStream();
            processor = processorFactory.createProcessorForSecurityConfiguration(is, callbackHandler);
        }
        finally {
            if (is != null) {
                is.close();
            }
        }
    }

    /**
     * Secures the given SoapMessage message in accordance with the defined security policy.
     *
     * @param soapMessage the message to be secured
     * @throws XwsSecuritySecurementException in case of errors
     * @throws IllegalArgumentException       when soapMessage is not a {@code SaajSoapMessage}
     */
    @Override
    protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
            throws XwsSecuritySecurementException {
        Assert.isTrue(soapMessage instanceof SaajSoapMessage, "XwsSecurityInterceptor requires a SaajSoapMessage. " +
                "Use a SaajSoapMessageFactory to create the SOAP messages.");
        SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage;
        try {
            ProcessingContext context = processor.createProcessingContext(saajSoapMessage.getSaajMessage());
            SOAPMessage result = processor.secureOutboundMessage(context);
            saajSoapMessage.setSaajMessage(result);
        }
        catch (XWSSecurityException ex) {
            throw new XwsSecuritySecurementException(ex.getMessage(), ex);
        }
        catch (WssSoapFaultException ex) {
            throw new XwsSecurityFaultException(ex.getFaultCode(), ex.getFaultString(), ex.getFaultActor());
        }
    }

    /**
     * Validates the given SoapMessage message in accordance with the defined security policy.
     *
     * @param soapMessage the message to be validated
     * @throws XwsSecurityValidationException in case of errors
     * @throws IllegalArgumentException       when soapMessage is not a {@code SaajSoapMessage}
     */
    @Override
    protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
            throws WsSecurityValidationException {
        Assert.isTrue(soapMessage instanceof SaajSoapMessage, "XwsSecurityInterceptor requires a SaajSoapMessage. " +
                "Use a SaajSoapMessageFactory to create the SOAP messages.");
        SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage;
        try {
            ProcessingContext context = processor.createProcessingContext(saajSoapMessage.getSaajMessage());
            SOAPMessage result = processor.verifyInboundMessage(context);
            saajSoapMessage.setSaajMessage(result);
        }
        catch (XWSSecurityException ex) {
            throw new XwsSecurityValidationException(ex.getMessage(), ex);
        }
        catch (WssSoapFaultException ex) {
            throw new XwsSecurityFaultException(ex.getFaultCode(), ex.getFaultString(), ex.getFaultActor());
        }
    }

  private SOAPMessage verifyInboundMessage(ProcessingContext context)
      throws XWSSecurityException {
    try {
      return processor.verifyInboundMessage(context);
    }
    catch (XWSSecurityException ex) {
      Throwable cause = ex.getCause();
      if (cause instanceof NullPointerException) {
        StackTraceElement[] stackTrace = cause.getStackTrace();
        if (stackTrace.length >= 1 &&
            Hashtable.class.getName().equals(stackTrace[0].getClassName())) {
          return verifyInboundMessage(context);
        }
      }
      throw ex;
    }
  }

  @Override
    protected void cleanUp() {
        if (callbackHandler != null) {
            try {
                CleanupCallback cleanupCallback = new CleanupCallback();
                callbackHandler.handle(new Callback[]{cleanupCallback});
            }
            catch (IOException ex) {
                logger.warn("Cleanup callback resulted in IOException", ex);
            }
            catch (UnsupportedCallbackException ex) {
                // ignore
            }
        }
    }
}
TOP

Related Classes of org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.