Package au.net.ocean.httpclient.auth.spnego

Source Code of au.net.ocean.httpclient.auth.spnego.SPNegoHTTPClient

/*******************************************************************************
* Copyright (c) 2007, Dave Whitla
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  * Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  * Neither the name of the copyright holder nor the names of contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/

package au.net.ocean.httpclient.auth.spnego;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;

import java.io.IOException;
import java.security.PrivilegedActionException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Created by dwhitla at Apr 15, 2007 3:09:49 PM
* <p/>
* Decorator
*
* @author <a href="mailto:dave.whitla@ocean.net.au">Dave Whitla</a>
* @version $Id: SPNegoHTTPClient.java 0 Apr 15, 2007 3:09:49 PM dwhitla $
*/
public class SPNegoHTTPClient extends HttpClient {

    private static final Logger LOGGER = Logger.getLogger(SPNegoHTTPClient.class.getName());
    private static final boolean MESSAGE_CONFIDENTIALITY = true;
    private static final boolean MESSAGE_INTEGRITY = true;
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String TOKEN_PREFIX = "Negotiate";

    private SPNegoCredentials credentials;
    private boolean mutualAuth;

    public SPNegoHTTPClient(SPNegoCredentials credentials, boolean mutualAuth) {
        super();
        this.credentials = credentials;
        this.mutualAuth = mutualAuth;

        AuthPolicy.registerAuthScheme(SPNegoAuthScheme.IDENTIFIER, SPNegoAuthScheme.class);
        List<String> authPriority = Arrays.asList(SPNegoAuthScheme.IDENTIFIER);
        Object existingAuthPriority = getParams().getParameter(AuthPolicy.AUTH_SCHEME_PRIORITY);
        if (existingAuthPriority != null) {
            authPriority.addAll((List<String>) existingAuthPriority);
        }
        getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPriority);
    }


    /**
     * Executes the given {@link org.apache.commons.httpclient.HttpMethod HTTP method}.
     *
     * @param method the {@link org.apache.commons.httpclient.HttpMethod HTTP method} to execute.
     * @return the method's response code
     * @throws java.io.IOException If an I/O (transport) error occurs. Some transport exceptions
     *                             can be recovered from.
     * @throws org.apache.commons.httpclient.HttpException
     *                             If a protocol exception occurs. Usually protocol exceptions
     *                             cannot be recovered from.
     */
    @Override
    public int executeMethod(HttpMethod method) throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, null);
        }
        try {
            return super.executeMethod(method);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }

    /**
     * Executes the given {@link org.apache.commons.httpclient.HttpMethod HTTP method} using custom
     * {@link org.apache.commons.httpclient.HostConfiguration host configuration}.
     *
     * @param hostConfiguration The {@link org.apache.commons.httpclient.HostConfiguration host configuration} to use.
     * @param method            the {@link org.apache.commons.httpclient.HttpMethod HTTP method} to execute.
     * @return the method's response code
     * @throws java.io.IOException If an I/O (transport) error occurs. Some transport exceptions
     *                             can be recovered from.
     * @throws org.apache.commons.httpclient.HttpException
     *                             If a protocol exception occurs. Usually protocol exceptions
     *                             cannot be recovered from.
     * @since 2.0
     */
    @Override
    public int executeMethod(final HostConfiguration hostConfiguration, final HttpMethod method) throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, null);
        }
        try {
            return super.executeMethod(hostConfiguration, method);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }

    /**
     * Executes the given {@link org.apache.commons.httpclient.HttpMethod HTTP method} using the given custom
     * {@link org.apache.commons.httpclient.HostConfiguration host configuration} with the given custom
     * {@link org.apache.commons.httpclient.HttpState HTTP state}.
     *
     * @param hostconfig The {@link org.apache.commons.httpclient.HostConfiguration host configuration} to use.
     * @param method     the {@link org.apache.commons.httpclient.HttpMethod HTTP method} to execute.
     * @param state      the {@link org.apache.commons.httpclient.HttpState HTTP state} to use when executing the method.
     *                   If <code>null</code>, the state returned by {@link #getState} will be used instead.
     * @return the method's response code
     * @throws java.io.IOException If an I/O (transport) error occurs. Some transport exceptions
     *                             can be recovered from.
     * @throws org.apache.commons.httpclient.HttpException
     *                             If a protocol exception occurs. Usually protocol exceptions
     *                             cannot be recovered from.
     * @since 2.0
     */
    @Override
    public int executeMethod(HostConfiguration hostconfig, final HttpMethod method, final HttpState state) throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, null);
        }
        try {
            return super.executeMethod(hostconfig, method, state);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }

    public int executeMethod(HttpMethod method, String servicePrincipal) throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, servicePrincipal);
        }
        try {
            return super.executeMethod(method);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }


    public int executeMethod(final HostConfiguration hostConfiguration, final HttpMethod method, String servicePrincipal)
            throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, servicePrincipal);
        }
        try {
            return super.executeMethod(hostConfiguration, method);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }

    public int executeMethod(HostConfiguration hostconfig,
                             final HttpMethod method,
                             final HttpState state,
                             String servicePrincipal) throws IOException {
        if (method.getDoAuthentication()) {
            setupGSSContext(method, servicePrincipal);
        }
        try {
            return super.executeMethod(hostconfig, method, state);
        } finally {
            if (method.getDoAuthentication()) {
                closeGSSContext();
            }
        }
    }

    private void setupGSSContext(HttpMethod method, String servicePrincipal) throws HttpException {
        URI uri = method.getURI();
        if (servicePrincipal == null || servicePrincipal.trim().length() == 0) {
            servicePrincipal = "HTTP/" + uri.getHost();
        }
        try {
            credentials.createGSSContext(servicePrincipal);
        } catch (PrivilegedActionException e) {
            throw new HttpException("PrivilegedActionException", e);
        } catch (GSSException e) {
            throw new HttpException("GSSException", e);
        }
        GSSContext gssContext = credentials.getGSSContext();
        try {
            // hack because HttpClient preemtive auth is broken wrt spnego as at 3.0.1
            if (getParams().isAuthenticationPreemptive()) {
                LOGGER.log(Level.INFO, "Using preemptive SPNego authentication");
                byte[] token = new Base64().encode(gssContext.initSecContext(new byte[0], 0, 0));
                LOGGER.log(Level.INFO, "Sending \"{0}\" {1} header", new String[]{TOKEN_PREFIX, AUTHORIZATION_HEADER});
                method.setRequestHeader(AUTHORIZATION_HEADER, MessageFormat.format("{0} {1}", TOKEN_PREFIX, new String(token)));
                getParams().setAuthenticationPreemptive(false);
            }
            gssContext.requestMutualAuth(mutualAuth);
            gssContext.requestConf(MESSAGE_CONFIDENTIALITY);
            gssContext.requestInteg(MESSAGE_INTEGRITY);
        } catch (GSSException e) {
            LOGGER.log(Level.SEVERE, "Caught GSSException setting options on GSSContext", e);
        }
        AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort(), credentials.getRealm());
        getState().setCredentials(authScope, credentials);
    }

    private void closeGSSContext() {
        try {
            credentials.closeGSSContext();
        } catch (GSSException e) {
            LOGGER.log(Level.WARNING, "Caught GSSException closing context", e);
        }
    }

}
TOP

Related Classes of au.net.ocean.httpclient.auth.spnego.SPNegoHTTPClient

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.