org.paxle.gui.impl.HttpAuthManager.java Source code

Java tutorial

Introduction

Here is the source code for org.paxle.gui.impl.HttpAuthManager.java

Source

/**
 * This file is part of the Paxle project.
 * Visit http://www.paxle.net for more information.
 * Copyright 2007-2010 the original author or authors.
 *
 * Licensed under the terms of the Common Public License 1.0 ("CPL 1.0").
 * Any use, reproduction or distribution of this program constitutes the recipient's acceptance of this agreement.
 * The full license text is available under http://www.opensource.org/licenses/cpl1.0.txt
 * or in the file LICENSE.txt in the root directory of the Paxle distribution.
 *
 * Unless required by applicable law or agreed to in writing, this software is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package org.paxle.gui.impl;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Bundle;
import org.osgi.service.http.HttpContext;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
import org.paxle.gui.IServletManager;
import org.paxle.gui.impl.servlets.LoginView;

@Component(immediate = true, metatype = false)
@Service(IHttpAuthManager.class)
public class HttpAuthManager implements IHttpAuthManager {
    public static final String USER_HTTP_PASSWORD = "http.password";
    public static final String USER_HTTP_LOGIN = "http.login";

    /**
     * For logging
     */
    private Log logger = LogFactory.getLog(HttpAuthManager.class);

    /**
     * The OSGI {@link UserAdmin} service required for user athentication
     */
    @Reference
    protected UserAdmin userAdmin;

    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
    protected IServletManager smanager;

    public User autoLogin(final HttpServletRequest request) {
        User user = null;

        final String[] autoLoginProperties = new String[] { "org.paxle.gui.autologin.user",
                "org.paxle.gui.autologin.user." + request.getRemoteHost(),
                "org.paxle.gui.autologin.user." + request.getRemoteAddr() };

        for (String autoLoginProperty : autoLoginProperties) {
            String autoLoginUser = System.getProperty(autoLoginProperty);
            if (autoLoginUser != null && autoLoginUser.length() > 0) {
                user = userAdmin.getUser(USER_HTTP_LOGIN, System.getProperty(autoLoginProperty));
                if (user != null)
                    break;
            }
        }

        return user;
    }

    public User httpAuth(final HttpServletRequest request, String httpAuthHeader)
            throws UnsupportedEncodingException {
        if (httpAuthHeader == null || httpAuthHeader.length() <= "Basic ".length()) {
            return null;
        }

        // base64 decode and get username + password
        byte[] authBytes = Base64.decodeBase64(httpAuthHeader.substring("Basic ".length()).getBytes("UTF-8"));
        httpAuthHeader = new String(authBytes, "UTF-8");
        String[] authData = httpAuthHeader.split(":");
        if (authData.length == 0) {
            logger.info(String.format("[%s] No user-authentication data found to access '%s'.",
                    request.getRemoteHost(), request.getRequestURI()));
            return null;
        }

        // extracting username + password
        String userName = authData[0];
        String password = authData.length == 1 ? "" : authData[1];

        return authenticatedAs(request, userName, password);
    }

    public User authenticatedAs(final HttpServletRequest request, final String userName, String password) {
        final User user = userAdmin.getUser(USER_HTTP_LOGIN, userName);
        if (user == null) {
            logger.info(String.format("[%s] No user found for username '%s'.", request.getRemoteHost(), userName));
            return null;
        }

        if (!user.hasCredential(USER_HTTP_PASSWORD, password)) {
            logger.info(String.format("[%s] Wrong password for username '%s'.", request.getRemoteHost(), userName));
            return null;
        }

        Authorization authorization = userAdmin.getAuthorization(user);
        if (authorization == null) {
            logger.info(String.format("[%s] No authorization found for username '%s'.", request.getRemoteHost(),
                    userName));
            return null;
        }

        //      if (!authorization.hasRole("Administrators")) {
        //         this.logger.warn(String.format(""))
        //      }

        return user;
    }

    public HttpContext createHttpAuthContext(Bundle bundle) {
        return new HttpContextAuth(bundle);
    }

    /*
     * User authentication here. Please read
     * http://www2.osgi.org/javadoc/r4/index.html to see how this could
     * be used in combination with the OSGI User Admin Service
     * (http://www2.osgi.org/javadoc/r4/org/osgi/service/useradmin/package-summary.html)
     */
    private class HttpContextAuth implements HttpContext {
        private final Bundle bundle;

        public HttpContextAuth(Bundle bundle) {
            this.bundle = bundle;
        }

        public String getMimeType(String name) {
            return null;
        }

        public URL getResource(String name) {
            return bundle.getResource(name);
        }

        public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException {
            // check if there is any http-auth header
            String httpAuth = request.getHeader("Authorization");

            // Get the session
            HttpSession session = request.getSession(true);

            // check if we are already authenticated
            Object done = session.getAttribute("logon.isDone"); // marker object

            // determine if http-auth can be done
            if (done == null) {
                // auto login feature
                User user = autoLogin(request);

                // auth. user via http-auth header
                if (user == null)
                    user = httpAuth(request, httpAuth);
                if (user != null) {
                    done = Boolean.TRUE;
                    session.setAttribute("logon.isDone", done);

                    // set user-data into the session
                    session.setAttribute(HttpContext.AUTHENTICATION_TYPE, HttpServletRequest.BASIC_AUTH);
                    session.setAttribute(HttpContext.AUTHORIZATION, userAdmin.getAuthorization(user));
                    session.setAttribute(HttpContext.REMOTE_USER, user);
                }
            }

            // if we are still not authenticated, try to use form-based login
            if (done == null) {
                StringBuilder target = new StringBuilder(request.getRequestURI());
                if (request.getQueryString() != null) {
                    target.append("?").append(request.getQueryString());
                }

                // No logon.isDone means he hasn't logged in.
                // Save the request URL as the true target and redirect to the login page.
                // XXX: this currently just works for GET requests
                session.setAttribute("login.target", target.toString());
                response.sendRedirect(String.format("%s://%s:%d%s", request.getScheme(), request.getServerName(),
                        Integer.valueOf(request.getServerPort()),
                        smanager.getFullServletPath(LoginView.class.getName())));
                return false;
            }

            // according to the OSGi Spec. we need to set this.
            request.setAttribute(HttpContext.AUTHENTICATION_TYPE,
                    session.getAttribute(HttpContext.AUTHENTICATION_TYPE));
            request.setAttribute(HttpContext.AUTHORIZATION, session.getAttribute(HttpContext.AUTHORIZATION));
            request.setAttribute(HttpContext.REMOTE_USER, session.getAttribute(HttpContext.REMOTE_USER));

            return true;
        }

    }
}