001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.proxy.handlers.http.basic;
021
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.mina.core.filterchain.IoFilter.NextFilter;
027import org.apache.mina.proxy.ProxyAuthException;
028import org.apache.mina.proxy.handlers.http.AbstractAuthLogicHandler;
029import org.apache.mina.proxy.handlers.http.HttpProxyConstants;
030import org.apache.mina.proxy.handlers.http.HttpProxyRequest;
031import org.apache.mina.proxy.handlers.http.HttpProxyResponse;
032import org.apache.mina.proxy.session.ProxyIoSession;
033import org.apache.mina.proxy.utils.StringUtilities;
034import org.apache.mina.util.Base64;
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038/**
039 * HttpBasicAuthLogicHandler.java - HTTP Basic authentication mechanism logic handler.
040 * 
041 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
042 * @since MINA 2.0.0-M3
043 */
044public class HttpBasicAuthLogicHandler extends AbstractAuthLogicHandler {
045    private final static Logger logger = LoggerFactory.getLogger(HttpBasicAuthLogicHandler.class);
046
047    /**
048     * Build an HttpBasicAuthLogicHandler
049     * 
050     * @param proxyIoSession The proxy session
051     * @throws ProxyAuthException If we had a probelm during the proxy authentication
052     */
053    public HttpBasicAuthLogicHandler(final ProxyIoSession proxyIoSession) throws ProxyAuthException {
054        super(proxyIoSession);
055
056        ((HttpProxyRequest) request).checkRequiredProperties(HttpProxyConstants.USER_PROPERTY,
057                HttpProxyConstants.PWD_PROPERTY);
058    }
059
060    /**
061     * {@inheritDoc}
062     */
063    @Override
064    public void doHandshake(final NextFilter nextFilter) throws ProxyAuthException {
065        logger.debug(" doHandshake()");
066
067        if (step > 0) {
068            throw new ProxyAuthException("Authentication request already sent");
069        }
070
071        // Send request
072        HttpProxyRequest req = (HttpProxyRequest) request;
073        Map<String, List<String>> headers = req.getHeaders() != null ? req.getHeaders()
074                : new HashMap<String, List<String>>();
075
076        String username = req.getProperties().get(HttpProxyConstants.USER_PROPERTY);
077        String password = req.getProperties().get(HttpProxyConstants.PWD_PROPERTY);
078
079        StringUtilities.addValueToHeader(headers, "Proxy-Authorization",
080                "Basic " + createAuthorization(username, password), true);
081
082        addKeepAliveHeaders(headers);
083        req.setHeaders(headers);
084
085        writeRequest(nextFilter, req);
086        step++;
087    }
088
089    /**
090     * Computes the authorization header value.
091     * 
092     * @param username the user name
093     * @param password the user password
094     * @return the authorization header value as a string
095     */
096    public static String createAuthorization(final String username, final String password) {
097        return new String(Base64.encodeBase64((username + ":" + password).getBytes()));
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    @Override
104    public void handleResponse(final HttpProxyResponse response) throws ProxyAuthException {
105        if (response.getStatusCode() != 407) {
106            throw new ProxyAuthException("Received error response code (" + response.getStatusLine() + ").");
107        }
108    }
109}