001    /*
002     * Copyright 2007 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.ksb.security.httpinvoker;
017    
018    import java.io.ByteArrayOutputStream;
019    import java.io.IOException;
020    
021    import org.apache.commons.codec.binary.Base64;
022    import org.apache.commons.httpclient.HttpClient;
023    import org.apache.commons.httpclient.methods.PostMethod;
024    import org.kuali.rice.core.security.credentials.CredentialsSource;
025    import org.kuali.rice.ksb.messaging.KSBHttpInvokerRequestExecutor;
026    import org.kuali.rice.ksb.messaging.ServiceInfo;
027    import org.kuali.rice.ksb.security.credentials.UsernamePasswordCredentials;
028    import org.springframework.remoting.httpinvoker.HttpInvokerClientConfiguration;
029    import org.springframework.util.Assert;
030    
031    
032    /**
033     * Extension to {@link KSBHttpInvokerRequestExecutor} that retrieves
034     * credentials from the CredentialsSource and places them in a BASIC HTTP
035     * Authorization header.
036     * 
037     * @author Kuali Rice Team (rice.collab@kuali.org)
038     * @since 0.9
039     */
040    public final class AuthenticationCommonsHttpInvokerRequestExecutor extends
041        KSBHttpInvokerRequestExecutor {
042    
043        /**
044         * Source of the credentials to pass via BASIC AUTH.
045         */
046        private final CredentialsSource credentialsSource;
047    
048        /**
049         * Details about the service that the CredentialsSource may need.
050         */
051        private final ServiceInfo serviceInfo;
052    
053        /**
054         * Constructor that accepts the CredentialsSource and Service Info.
055         * 
056         * @param credentialsSource the source of credentials.
057         * @param serviceInfo information about the service.
058         */
059        public AuthenticationCommonsHttpInvokerRequestExecutor(final HttpClient httpClient, 
060            final CredentialsSource credentialsSource, final ServiceInfo serviceInfo) {
061            super(httpClient);
062            Assert.notNull(credentialsSource, "credentialsSource cannot be null.");
063            Assert.notNull(serviceInfo, "serviceInfo cannot be null.");
064            this.credentialsSource = credentialsSource;
065            this.serviceInfo = serviceInfo;
066        }
067    
068        /**
069         * Overridden to obtain the Credentials from the CredentialsSource and pass
070         * them via HTTP BASIC Authorization.
071         */
072    
073        protected void setRequestBody(final HttpInvokerClientConfiguration config,
074            final PostMethod postMethod, final ByteArrayOutputStream baos) throws IOException {
075            final UsernamePasswordCredentials credentials = (UsernamePasswordCredentials) this.credentialsSource.getCredentials(this.serviceInfo.getEndpointUrl());
076    
077            final String base64 = credentials.getUsername() + ":"
078            + credentials.getPassword();
079            postMethod.addRequestHeader("Authorization", "Basic " + new String(Base64.encodeBase64(base64.getBytes())));
080    
081            if (logger.isDebugEnabled()) {
082                logger
083                    .debug("HttpInvocation now presenting via BASIC authentication CredentialsSource-derived: "
084                        + credentials.getUsername());
085            }
086            
087            super.setRequestBody(config, postMethod, baos);
088        }
089    }