org.josso.alfresco.agent.AlfrescoSSOAgentFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.josso.alfresco.agent.AlfrescoSSOAgentFilter.java

Source

/*
 * JOSSO: Java Open Single Sign-On
 *
 * Copyright 2004-2009, Atricore, Inc.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 */

package org.josso.alfresco.agent;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.TicketComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.FacesHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.josso.agent.Lookup;
import org.josso.agent.http.HttpSSOAgent;
import org.josso.agent.http.WebAccessControlUtil;
import org.josso.gateway.SSONameValuePair;
import org.josso.gateway.identity.SSOUser;
import org.josso.gateway.identity.service.SSOIdentityManagerService;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.faces.context.FacesContext;
import javax.security.auth.Subject;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;
import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * JOSSO Servlet Filter for Alfresco SSO Agent
 * The fillter will handle web logic to authenticate, login and logout users.
 * <p/>
 * Date: Jun 10, 2010
 * Time: 16:00:00
 */

public class AlfrescoSSOAgentFilter implements Filter {

    private static final String KEY_SESSION_MAP = "org.josso.servlet.agent.sessionMap";

    private ServletContext _ctx;
    private HttpSSOAgent _agent;

    private ServiceRegistry serviceRegistry;
    private PersonService personService;
    private PermissionService permissionService;
    private MutableAuthenticationService authenticationService;
    private AuthenticationComponent authComponent;
    private TicketComponent ticketComponent;

    /**
     * Logger
     */
    private static final Log logger = LogFactory.getLog(AlfrescoSSOAgentFilter.class);

    public void init(FilterConfig filterConfig) throws ServletException {
        // Validate and update our current component state
        _ctx = filterConfig.getServletContext();
        WebApplicationContext webCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(_ctx);
        _ctx.setAttribute(KEY_SESSION_MAP, new HashMap());

        if (_agent == null) {

            try {

                Lookup lookup = Lookup.getInstance();
                lookup.init("josso-agent-config.xml"); // For spring compatibility ...

                // We need at least an abstract SSO Agent
                _agent = (HttpSSOAgent) lookup.lookupSSOAgent();
                if (logger.isDebugEnabled())
                    _agent.setDebug(1);
                _agent.start();

                // Publish agent in servlet context
                filterConfig.getServletContext().setAttribute("org.josso.agent", _agent);

            } catch (Exception e) {
                throw new ServletException("Error starting SSO Agent : " + e.getMessage(), e);
            }
        }

        try {
            this.serviceRegistry = (ServiceRegistry) webCtx.getBean(ServiceRegistry.SERVICE_REGISTRY);
            this.authenticationService = serviceRegistry.getAuthenticationService();
            this.personService = serviceRegistry.getPersonService();
            this.permissionService = (PermissionService) webCtx.getBean("PermissionService");
            this.authComponent = (AuthenticationComponent) webCtx.getBean("AuthenticationComponent");
            this.ticketComponent = (TicketComponent) webCtx.getBean("ticketComponent");
        } catch (BeansException e) {
            e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {

        HttpServletRequest hReq = (HttpServletRequest) request;
        HttpServletResponse hRes = (HttpServletResponse) response;
        HttpSession hSession = hReq.getSession();

        Cookie jCookie = getJossoCookie(hReq);
        // token is jossoSessionId
        String token = "";
        if (jCookie != null && !jCookie.getValue().equals("-"))
            token = jCookie.getValue();

        boolean isLoginRequest = isLoginRequest(hReq);
        boolean isLogoutRequest = isLogoutRequest(hReq);
        boolean isGuestRequest = (("").equals(token) && !isLoginRequest && !isLogoutRequest);
        boolean isNormalRequest = (!("").equals(token) && !isLoginRequest && !isLogoutRequest);

        String alfrescoContext = hReq.getContextPath();

        if (isLoginRequest) {
            String alfRedirect = (String) hSession.getAttribute("_alfRedirect");
            if (alfRedirect == null) {
                alfRedirect = "";
            }
            _agent.setAttribute(hReq, hRes, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, alfRedirect);
            //set non cache headers
            _agent.prepareNonCacheResponse(hRes);
            hRes.sendRedirect(alfrescoContext + _agent.getJossoLoginUri());
        }

        if (isLogoutRequest) {
            hSession.invalidate();
            hRes.sendRedirect(alfrescoContext + _agent.getJossoLogoutUri());
        }

        if (isGuestRequest) {
            filterChain.doFilter(hReq, hRes);
        }

        if (isNormalRequest) {
            try {
                SSOIdentityManagerService im = Lookup.getInstance().lookupSSOAgent().getSSOIdentityManager();
                SSOUser ssoUser = im.findUserInSession(token, token);
                String principal = "";
                if (ssoUser != null)
                    principal = ssoUser.getName();

                if (!existUser(principal)) { //user does not exist, create new one
                    HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
                    properties.put(ContentModel.PROP_USERNAME, principal);

                    for (SSONameValuePair nameValuePair : ssoUser.getProperties()) {

                        if (nameValuePair.getName().equals("user.name")) {
                            properties.put(ContentModel.PROP_FIRSTNAME, nameValuePair.getValue());

                        } else if (nameValuePair.getName()
                                .equals("urn:org:atricore:idbus:user:property:firstName")) {
                            properties.put(ContentModel.PROP_FIRSTNAME, nameValuePair.getValue());

                        } else if (nameValuePair.getName().equals("user.lastName")) {
                            properties.put(ContentModel.PROP_LASTNAME, nameValuePair.getValue());

                        } else if (nameValuePair.getName()
                                .equals("urn:org:atricore:idbus:user:property:lastName")) {
                            properties.put(ContentModel.PROP_LASTNAME, nameValuePair.getValue());

                        } else if (nameValuePair.getName().equals("email")) {
                            properties.put(ContentModel.PROP_EMAIL, nameValuePair.getValue());

                        } else if (nameValuePair.getName().equals("urn:org:atricore:idbus:user:property:email")) {
                            properties.put(ContentModel.PROP_EMAIL, nameValuePair.getValue());
                        }

                    }
                    createUser(principal, properties);
                }

                setAuthenticatedUser(hReq, hRes, hSession, principal);
                filterChain.doFilter(hReq, hRes);
            } catch (Exception e) {
                logger.error(e, e);
            }
        }
    }

    public void destroy() {
    }

    private Cookie getJossoCookie(HttpServletRequest hreq) {
        Cookie cookie = null;
        Cookie cookies[] = hreq.getCookies();
        if (cookies == null)
            cookies = new Cookie[0];
        for (int i = 0; i < cookies.length; i++) {
            if (org.josso.gateway.Constants.JOSSO_SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) {
                cookie = cookies[i];
                break;
            }
        }

        return cookie;
    }

    private boolean isLoginRequest(HttpServletRequest request) {
        Enumeration parameterNames = request.getParameterNames();
        String alfRedirect = (String) request.getSession().getAttribute("_alfRedirect");

        if (request.getRequestURI().endsWith("login.jsp") && !"".equals(alfRedirect))
            return true;

        while (parameterNames.hasMoreElements()) {
            String parameter = (String) parameterNames.nextElement();
            String[] string = request.getParameterValues(parameter);
            for (int i = 0; i < string.length; i++) {
                if (string[i] != null && string[i].contains(":login")) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isLogoutRequest(HttpServletRequest request) {
        Enumeration parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameter = (String) parameterNames.nextElement();
            String[] string = request.getParameterValues(parameter);
            for (int i = 0; i < string.length; i++) {
                if (string[i] != null && string[i].contains(":logout")) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean existUser(final String username) {
        AuthenticationUtil.RunAsWork<Boolean> existUserWork = new AuthenticationUtil.RunAsWork<Boolean>() {
            public Boolean doWork() throws Exception {
                return personService.personExists(username);
            }
        };
        Boolean result = AuthenticationUtil.runAs(existUserWork, AuthenticationUtil.getAdminUserName());

        return result.booleanValue();
    }

    public void createUser(final String username, final HashMap<QName, Serializable> userDetails) {
        AuthenticationUtil.RunAsWork<Object> createUserWork = new AuthenticationUtil.RunAsWork<Object>() {
            public Object doWork() throws Exception {
                authenticationService.createAuthentication(username, username.toCharArray());
                NodeRef newPerson = personService.createPerson(userDetails);
                permissionService.setPermission(newPerson, username, permissionService.getAllPermission(), true);
                authenticationService.setAuthenticationEnabled(username, true);
                return null;
            }
        };
        AuthenticationUtil.runAs(createUserWork, AuthenticationUtil.getAdminUserName());
    }

    protected void setAuthenticatedUser(final HttpServletRequest req, final HttpServletResponse res,
            final HttpSession httpSess, final String userName) {

        UserTransaction tx = serviceRegistry.getTransactionService().getUserTransaction();

        Subject.doAs(AlfrescoPrivilegdedActions.getAdminSubject(),
                AlfrescoPrivilegdedActions.clearCurrentSecurityContextAction(authComponent));
        ticketComponent.clearCurrentTicket();

        try {
            tx.begin();
            Subject.doAs(AlfrescoPrivilegdedActions.getAdminSubject(),
                    AlfrescoPrivilegdedActions.setCurrentUserAction(userName));
            Subject.doAs(AlfrescoPrivilegdedActions.getAdminSubject(),
                    AlfrescoPrivilegdedActions.createUserAction(serviceRegistry, userName, httpSess));

            FacesHelper.getFacesContext(req, res, _ctx);
            FacesContext fc = FacesContext.getCurrentInstance();
            Map session = fc.getExternalContext().getSessionMap();
            session.remove(AuthenticationHelper.SESSION_INVALIDATED);
            tx.commit();
        } catch (Throwable ex) {
            logger.error(ex);
            try {
                tx.rollback();
            } catch (Exception ex2) {
                logger.error("Failed to rollback transaction", ex2);
            }

            if (ex instanceof RuntimeException) {
                throw (RuntimeException) ex;
            } else {
                throw new RuntimeException("Failed to execute transactional method", ex);
            }
        }
    }
}