org.infoscoop.web.SessionManagerFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.infoscoop.web.SessionManagerFilter.java

Source

/* infoScoop OpenSource
 * Copyright (C) 2010 Beacon IT Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program 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 program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0-standalone.html>.
 */

/**
 *
 */
package org.infoscoop.web;

import java.io.IOException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
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.infoscoop.account.AuthenticationService;
import org.infoscoop.account.SessionCreateConfig;
import org.infoscoop.acl.ISPrincipal;
import org.infoscoop.acl.SecurityController;
import org.infoscoop.admin.web.PreviewImpersonationFilter;
import org.infoscoop.context.UserContext;
import org.infoscoop.dao.SessionDAO;
import org.infoscoop.dao.PropertiesDAO;
import org.infoscoop.util.RSAKeyManager;

/**
 * The filter which manages the login state.
 * We set the login module by a loginAuthentication that is in the initialization parameter.
 * <ul>
 *    <li>true:We perform the certification for the MSD login certification module.
 *    <li>false: In the case of Single-Sign-On environment.
 * </li>
 * @author dou
 * @author iwata
 * @author hr-endoh
 */
public class SessionManagerFilter implements Filter {
    private static Log log = LogFactory.getLog(SessionManagerFilter.class);
    public static String LOGINUSER_ID_ATTR_NAME = "Uid";
    public static String LOGINUSER_NAME_ATTR_NAME = "loginUserName";
    public static String LOGINUSER_SUBJECT_ATTR_NAME = "loginUser";
    public static String LOGINUSER_SESSION_ID_ATTR_NAME = "SessionId";

    private Collection excludePaths = new HashSet();
    private Collection<String> excludePathx = new HashSet<String>();
    private Collection redirectPaths = new HashSet();

    public void init(FilterConfig config) throws ServletException {

        String excludePathStr = config.getInitParameter("excludePath");
        if (excludePathStr != null) {
            String[] pathArray = excludePathStr.split(",");
            for (int i = 0; i < pathArray.length; i++) {
                String path = pathArray[i].trim();
                if (path.endsWith("*")) {
                    excludePathx.add(path.substring(0, path.length() - 1));
                } else {
                    excludePaths.add(path);
                }
            }
        }

        String redirectPathStr = config.getInitParameter("redirectPath");
        if (redirectPathStr != null) {
            String[] pathArray = redirectPathStr.split(",");
            for (int i = 0; i < pathArray.length; i++) {
                redirectPaths.add(pathArray[i].trim());
            }
        }
    }

    private String getUidFromHeader(HttpServletRequest req) {
        String uidHeader = SessionCreateConfig.getInstance().getUidHeader();
        boolean uidIgnoreCase = SessionCreateConfig.getInstance().isUidIgnoreCase();

        String uid = null;

        if (uidHeader != null) {
            uid = req.getHeader(uidHeader);

            if (log.isDebugEnabled()) {
                log.debug("Got UID from Header : [" + uid + "]");
            }
        } else {
            uid = req.getRemoteUser();
            if (log.isDebugEnabled()) {
                log.debug("Got UID from RemoteUser : [" + uid + "]");
            }
        }
        if (uid == null) {
            if (log.isInfoEnabled())
                log.info("uidHeader is null");
            return null;
        }

        if ("true".equalsIgnoreCase(req.getParameter(CheckDuplicateUidFilter.IS_PREVIEW))) {
            HttpSession session = req.getSession(true);
            String sessionUid = (String) session.getAttribute("Uid");
            String uidParam = req.getParameter("Uid");
            if (uidParam.equalsIgnoreCase(sessionUid)) {
                uid = uidParam;
                session.setAttribute("Uid", uid);
            }
        } else if (uidIgnoreCase && uid != null)
            uid = uid.toLowerCase();

        return uid.trim();
    }

    private String getUidFromSession(HttpServletRequest req) {
        HttpSession session = req.getSession(true);
        String uid = (String) session.getAttribute("Uid");
        String sessionId = req.getHeader("MSDPortal-SessionId");
        boolean uidIgnoreCase = SessionCreateConfig.getInstance().isUidIgnoreCase();

        if ("true".equalsIgnoreCase(req.getParameter(CheckDuplicateUidFilter.IS_PREVIEW))) {
            String uidParam = req.getParameter("Uid");
            if (uid.equalsIgnoreCase(uidParam)) {
                uid = uidParam;
                session.setAttribute("Uid", uid);
            }
        } else if (uidIgnoreCase && uid != null) {
            uid = uid.toLowerCase();

            session.setAttribute("Uid", uid);
        }

        if (uid == null) {
            if (sessionId != null) {
                session.setAttribute(LOGINUSER_SESSION_ID_ATTR_NAME, sessionId);
                return SessionDAO.newInstance().getUid(sessionId);
            }
        } else if (sessionId != null) {
            String oldSessionId = (String) session.getAttribute(LOGINUSER_SESSION_ID_ATTR_NAME);
            if (oldSessionId != null && !sessionId.equals(oldSessionId)) {
                session.invalidate();
                session = req.getSession(true);
                session.setAttribute(LOGINUSER_SESSION_ID_ATTR_NAME, sessionId);
                return SessionDAO.newInstance().getUid(sessionId);
            }
        }
        return uid;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpReq = (HttpServletRequest) request;
        if (log.isDebugEnabled()) {
            log.debug("Enter SessionManagerFilter form " + httpReq.getRequestURI());
        }

        if (request instanceof javax.servlet.http.HttpServletRequest) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;

            String uid = null;
            if (SessionCreateConfig.doLogin()) {
                uid = getUidFromSession(httpReq);

                if (uid != null) {
                    addUidToSession(uid, request);
                }

                if (redirectPaths.contains(httpReq.getServletPath())) {
                    httpResponse.addCookie(new Cookie("redirect_path", httpReq.getServletPath()));
                }
                if (uid == null && !isExcludePath(httpReq.getServletPath())) {
                    if (httpRequest.getHeader("MSDPortal-Ajax") != null) {
                        if (log.isInfoEnabled())
                            log.info("session timeout has occured. logoff automatically.");
                        httpResponse.setHeader(HttpStatusCode.HEADER_NAME, HttpStatusCode.MSD_SESSION_TIMEOUT);
                        httpResponse.sendError(500);
                        return;
                    }
                }
            } else {
                uid = getUidFromHeader(httpReq);
                if (uid == null)
                    uid = getUidFromSession(httpReq);
                if (uid != null) {
                    addUidToSession(uid, request);
                }
            }

            if (uid == null) {
                Cookie[] cookies = httpReq.getCookies();
                if (cookies != null) {
                    for (Cookie cookie : cookies) {
                        if (cookie.getName().equals("portal-credential")) {
                            int keepPeriod = 7;
                            try {
                                keepPeriod = Integer.parseInt(PropertiesDAO.newInstance()
                                        .findProperty("loginStateKeepPeriod").getValue());
                            } catch (Exception ex) {
                                log.warn("", ex);
                            }

                            if (keepPeriod <= 0) {
                                Cookie credentialCookie = new Cookie("portal-credential", "");
                                credentialCookie.setMaxAge(0);
                                credentialCookie.setPath("/");
                                httpResponse.addCookie(credentialCookie);

                                log.info("clear auto login credential [" + credentialCookie.getValue() + "]");
                            } else {
                                try {
                                    uid = tryAutoLogin(cookie);
                                    httpReq.getSession().setAttribute("Uid", uid);

                                    log.info("auto login success.");
                                } catch (Exception ex) {
                                    log.info("auto login failed.", ex);
                                }
                            }
                        }
                    }
                }
            }

            if (uid == null && SessionCreateConfig.doLogin() && !isExcludePath(httpReq.getServletPath())) {
                String requestUri = httpReq.getRequestURI();
                String loginUrl = requestUri.lastIndexOf("/manager/") > 0
                        ? requestUri.substring(0, requestUri.lastIndexOf("/")) + "/../login.jsp"
                        : "login.jsp";

                httpResponse.sendRedirect(loginUrl);
                return;
            }

            if (log.isInfoEnabled())
                log.info("### Access from user " + uid + " to " + httpReq.getRequestURL());

            // fix #42
            //         setUserInfo2Cookie(httpReq, (HttpServletResponse)response, uid);
            HttpSession session = httpRequest.getSession();

            Subject loginUser = (Subject) session.getAttribute(LOGINUSER_SUBJECT_ATTR_NAME);

            if (loginUser == null || (isChangeLoginUser(uid, loginUser)
                    && !(session instanceof PreviewImpersonationFilter.PreviewHttpSession))) {
                if (!SessionCreateConfig.getInstance().hasUidHeader() && uid != null) {
                    AuthenticationService service = AuthenticationService.getInstance();
                    try {
                        if (service != null)
                            loginUser = service.getSubject(uid);
                    } catch (Exception e) {
                        log.error("", e);
                    }
                }

                if (loginUser == null || isChangeLoginUser(uid, loginUser)) {
                    loginUser = new Subject();
                    loginUser.getPrincipals().add(new ISPrincipal(ISPrincipal.UID_PRINCIPAL, uid));
                }

                setLoginUserName(httpRequest, loginUser);

                for (Map.Entry entry : SessionCreateConfig.getInstance().getRoleHeaderMap().entrySet()) {
                    String headerName = (String) entry.getKey();
                    String roleType = (String) entry.getValue();
                    Enumeration headerValues = httpRequest.getHeaders(headerName);
                    while (headerValues.hasMoreElements()) {
                        String headerValue = (String) headerValues.nextElement();
                        try {
                            Set principals = loginUser.getPrincipals();
                            principals.add(new ISPrincipal(roleType, headerValue));
                            //                     loginUser.getPrincipals().add( roleType.getConstructor(paramTypes).newInstance(initArgs) );
                            if (log.isInfoEnabled())
                                log.info("Set principal to login subject: " + roleType + "=" + headerValue);
                        } catch (IllegalArgumentException e) {
                            log.error("", e);
                        } catch (SecurityException e) {
                            log.error("", e);
                        }
                    }

                }
                session.setAttribute(LOGINUSER_SUBJECT_ATTR_NAME, loginUser);
            }
            SecurityController.registerContextSubject(loginUser);
            if (httpRequest.getHeader("X-IS-TIMEZONE") != null) {
                int timeZoneOffset = 0;
                try {
                    timeZoneOffset = Integer.parseInt(httpRequest.getHeader("X-IS-TIMEZONE"));
                } catch (NumberFormatException e) {
                    if (log.isDebugEnabled())
                        log.debug(httpRequest.getHeader("X-IS-TIMEZONE"), e);
                } finally {
                    UserContext.instance().getUserInfo().setClientTimezoneOffset(timeZoneOffset);
                }
            }
        }
        chain.doFilter(request, response);

        if (log.isDebugEnabled()) {
            log.debug("Exit SessionManagerFilterform " + httpReq.getRequestURI());
        }

    }

    /**
     *
     * @param httpRequest
     * @param loginUser
     */
    private void setLoginUserName(HttpServletRequest httpRequest, Subject loginUser) {
        String loginUserName = null;
        String usernameHeader = SessionCreateConfig.getInstance().getUsernameHeader();
        if (usernameHeader != null)
            loginUserName = httpRequest.getHeader(usernameHeader);

        if (loginUserName == null)
            loginUserName = getUserNameFromSubject(loginUser);

        httpRequest.getSession().setAttribute(LOGINUSER_NAME_ATTR_NAME,
                (loginUserName != null) ? loginUserName : "");
    }

    private String getUserNameFromSubject(Subject loginUser) {
        Collection principals = loginUser.getPrincipals(ISPrincipal.class);

        for (Iterator it = principals.iterator(); it.hasNext();) {
            ISPrincipal p = (ISPrincipal) it.next();
            if (ISPrincipal.UID_PRINCIPAL.equals(p.getType())) {
                ISPrincipal isp = (ISPrincipal) p;
                return isp.getDisplayName();
            }
        }
        return null;
    }

    private boolean isChangeLoginUser(String uid, Subject loginUser) {
        Set principals = loginUser.getPrincipals(ISPrincipal.class);
        for (Iterator it = principals.iterator(); it.hasNext();) {
            ISPrincipal p = (ISPrincipal) it.next();
            if (ISPrincipal.UID_PRINCIPAL.equals(p.getType())) {
                if (uid != null && !uid.equals(p.getName()))
                    return true;
            }
        }
        return false;
    }

    /* fix #42
    private void setUserInfo2Cookie(HttpServletRequest request, HttpServletResponse response, String uid) {
        
    boolean isExistUid = false;
    Cookie[] cookies = request.getCookies();
    if(cookies != null){
        for(int i = 0; i < cookies.length; i++){
            if("Uid".equals(cookies[i].getName()) && cookies[i].getValue() != null && !"".equals(cookies[i].getValue())){
                isExistUid = true;
                break;
            }
        }
    }
    if(!isExistUid && uid != null){
        HttpServletResponse httpResponse = (HttpServletResponse)response;
        httpResponse.addCookie(new Cookie("Uid", uid));
        if(usernameHeader != null){
            String userName = request.getHeader(usernameHeader);
            if(userName != null){
                httpResponse.addCookie(new Cookie("UserName", userName));
            }
        }
        
    }
        
    }
    */

    private void addUidToSession(String uid, ServletRequest request) {
        HttpSession session = ((HttpServletRequest) request).getSession();
        if (session.getAttribute("Uid") != null)
            return;
        session.setAttribute("Uid", uid);
        if (log.isInfoEnabled()) {
            log.info("Add Uid To session : [" + uid + "]");
        }
    }

    public void destroy() {
    }

    private boolean isExcludePath(String path) {
        if (excludePaths.contains(path))
            return true;

        for (String p : excludePathx) {
            if (path.startsWith(p))
                return true;
        }

        return false;
    }

    private String tryAutoLogin(Cookie cookie) throws Exception {
        String credentialStr = cookie.getValue();

        try {
            String[] credentialPair = credentialStr.split(":");
            String portalUid = new String(Base64.decodeBase64(credentialPair[0].getBytes("UTF-8")), "UTF-8");
            String portalPassword = RSAKeyManager.getInstance().decrypt(credentialPair[1]);

            AuthenticationService service = AuthenticationService.getInstance();
            if (service == null)
                throw new Exception("No bean named \"authenticationService\" is defined."
                        + " When loginAuthentication property is true,"
                        + " authenticationService must be defined.");

            service.login(portalUid, portalPassword);

            portalUid = portalUid.trim();
            return portalUid;
        } catch (Exception ex) {
            //         log.info("Auto Login Failed by ["+credentialStr+"]");

            throw ex;
        }
    }
}