Package org.joget.apps.workflow.security

Source Code of org.joget.apps.workflow.security.WorkflowHttpAuthProcessingFilter

package org.joget.apps.workflow.security;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Locale;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.joget.apps.app.service.AppUtil;
import org.joget.commons.util.LogUtil;
import org.joget.commons.util.ResourceBundleUtil;
import org.joget.commons.util.SecurityUtil;
import org.joget.commons.util.SetupManager;
import org.joget.commons.util.StringUtil;
import org.joget.directory.model.User;
import org.joget.directory.model.service.DirectoryManager;
import org.joget.directory.model.service.DirectoryUtil;
import org.joget.directory.model.service.UserSecurity;
import org.joget.workflow.model.dao.WorkflowHelper;
import org.joget.workflow.model.service.WorkflowUserManager;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.TargetUrlResolver;
import org.springframework.security.ui.TargetUrlResolverImpl;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.security.util.TextUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.LocaleResolver;

public class WorkflowHttpAuthProcessingFilter extends AuthenticationProcessingFilter {

    private WorkflowUserManager workflowUserManager;
    private DirectoryManager directoryManager;
    private SetupManager setupManager;
    private LocaleResolver localeResolver;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException {
        return authenticate(request);
    }

    @Override
    public void doFilterHttp(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        Boolean requiresAuthentication;
        try {
            if (localeResolver != null) {
                Locale locale = localeResolver.resolveLocale(request);
                LocaleContextHolder.setLocale(locale);
            }
           
            // clear current app in thread
            AppUtil.resetAppDefinition();
           
            // clear current user
            workflowUserManager.clearCurrentThreadUser();
           
            requiresAuthentication = requiresAuthentication(request, response);

            super.doFilterHttp(request, response, chain);
           
            String uri = request.getRequestURI();
            if (requiresAuthentication && !uri.startsWith(request.getContextPath() + "/j_spring_security_check") && !response.isCommitted()) {
                chain.doFilter(request, response);
            }
        } finally {
            /*
            // Uncomment this block to force JSON API requests to authenticate on every call
            String uri = request.getRequestURI();
            if (requiresAuthentication && uri.startsWith(request.getContextPath() + "/web/json") && !uri.contains("/web/json/directory/user/sso")) {
                // don't store authentication in session for json calls
                SecurityContextHolder.getContext().setAuthentication(null);
            }           
            */

            UserSecurity us = DirectoryUtil.getUserSecurity();
            if (us != null) {
                us.requestPostProcessing();
            }
           
            // clear current user
            workflowUserManager.clearCurrentThreadUser();
            LocaleContextHolder.resetLocaleContext();
        }
    }
   
    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        boolean isAnonymous = workflowUserManager.isCurrentUserAnonymous();
        boolean requiresAuth = false;
        String uri = request.getRequestURI();
        int pathParamIndex = uri.indexOf(';');

        if (pathParamIndex > 0) {
            // strip everything after the first semi-colon
            uri = uri.substring(0, pathParamIndex);
        }

        UserSecurity us = DirectoryUtil.getUserSecurity();
        if ((super.obtainUsername(request) != null)) {
            // request contains j_username, force authentication
            requiresAuth = true;
        } else if (us != null) {
            uri = uri.substring(request.getContextPath().length());
            if (us.getAuthenticateAllApi() && uri.startsWith("/web/json/") && (!uri.startsWith("/web/json/plugin") || uri.startsWith("/web/json/plugin/list")) && !uri.startsWith("/web/json/directory/user/sso") && !uri.startsWith("/web/json/workflow/currentUsername") && !uri.startsWith("/web/json/apps/published/userviews") && isAnonymous) {
                // authenticateAllApi flag is true, so force authentication for all json calls except for plugin, sso, and published userview calls
                requiresAuth = true;
            } else if (us.getForceSessionTimeout() && !isAnonymous) {
                // logged in, but timed out
                requiresAuth = true;
            }
        }
       
        if (!requiresAuth) {
            requiresAuth = uri.endsWith(request.getContextPath() + getFilterProcessesUrl());
        }
       
        if (requiresAuth) {
            // generate new session to avoid session fixation vulnerability
            HttpSession session = request.getSession(false);
            if (session != null) {
                SavedRequest savedRequest = (SavedRequest) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY);
                session.invalidate();
                session = request.getSession(true);
                if (savedRequest != null) {
                    session.setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
                }
            }
        }
        return requiresAuth;
    }

    protected Authentication authenticate(HttpServletRequest request) throws AuthenticationException {
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
       
        boolean isAnonymous = workflowUserManager.isCurrentUserAnonymous();
        UserSecurity us = DirectoryUtil.getUserSecurity();
        if (us != null && us.getForceSessionTimeout() && !isAnonymous) {
            throw new BadCredentialsException(ResourceBundleUtil.getMessage("authentication.failed.sessionTimeOut"));
        }
       
        Authentication auth = null;

        // check for username/password in request
        String username = super.obtainUsername(request);
        String password = super.obtainPassword(request);

        String loginAs = request.getParameter("loginAs");
        String loginHash = request.getParameter("hash");
       
        // Place the last username attempted into HttpSession for views
        HttpSession session = request.getSession(false);

        if (session != null || getAllowSessionCreation()) {
            request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextUtils.escapeEntities(username));
        }

        if (username != null && (password != null || loginHash != null)) {
            User currentUser = null;

            //diable master login based on UserSecurity
            if (us != null && us.getDisableHashLogin()) {
                loginAs = null;
            }
           
            if (loginAs != null) {
                String masterLoginUsername = getSetupManager().getSettingValue("masterLoginUsername");
                String masterLoginPassword = getSetupManager().getSettingValue("masterLoginPassword");
               
                //decryt masterLoginPassword
                masterLoginPassword = SecurityUtil.decrypt(masterLoginPassword);

                if ((masterLoginUsername != null && masterLoginUsername.trim().length() > 0) &&
                        (masterLoginPassword != null && masterLoginPassword.trim().length() > 0)) {

                    User master = new User();
                    master.setUsername(masterLoginUsername.trim());
                    master.setPassword(StringUtil.md5Base16(masterLoginPassword.trim()));

                    if (username.trim().equals(master.getUsername()) &&
                            ((password != null && StringUtil.md5Base16(password.trim()).equalsIgnoreCase(master.getPassword())) ||
                            (loginHash != null && loginHash.trim().equalsIgnoreCase(master.getLoginHash())))) {
                        currentUser = directoryManager.getUserByUsername(loginAs);
                        if (currentUser != null) {
                            WorkflowUserDetails user = new WorkflowUserDetails(currentUser);
                           
                            auth = new UsernamePasswordAuthenticationToken(user, user.getUsername(), user.getAuthorities());
                            super.setDetails(request, (UsernamePasswordAuthenticationToken) auth);
                        } else {
                            LogUtil.info(getClass().getName(), "Authentication for user " + loginAs + ": " + false);
           
                            WorkflowHelper workflowHelper = (WorkflowHelper) AppUtil.getApplicationContext().getBean("workflowHelper");
                            workflowHelper.addAuditTrail("WorkflowHttpAuthProcessingFilter", "authenticate", "Authentication for user " + loginAs + ": " + false);
                       
                            throw new BadCredentialsException("");
                        }
                    }
                }
            } else {
                if (loginHash != null) {
                    password = loginHash;
                }
                if (password != null) {
                    // use existing authentication manager
                    try {
                        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username.trim(), password.trim());
                        super.setDetails(request, authRequest);

                        auth = getAuthenticationManager().authenticate(authRequest);

                        // no direct way in Spring Security 2, so use reflection to clear password in token
                        Field field = null;
                        try {
                            field = auth.getClass().getDeclaredField("credentials");
                            field.setAccessible(true);
                            field.set(auth, null);
                        } catch (Exception ex) {
                            LogUtil.error(getClass().getName(), ex, "Error clearing credentials in token");
                        } finally {
                            if (field != null) {
                                field.setAccessible(false);
                            }
                        }
                       
                        if (auth.isAuthenticated()) {
                            currentUser = directoryManager.getUserByUsername(username);
                        }
                    } catch (BadCredentialsException be) {
                        LogUtil.info(getClass().getName(), "Authentication for user " + ((loginAs == null) ? username : loginAs) + ": " + false);
           
                        WorkflowHelper workflowHelper = (WorkflowHelper) AppUtil.getApplicationContext().getBean("workflowHelper");
                        workflowHelper.addAuditTrail("WorkflowHttpAuthProcessingFilter", "authenticate", "Authentication for user " + ((loginAs == null) ? username : loginAs) + ": " + false);
           
                        throw be;
                    }
                }
            }

            if (currentUser != null) {
                workflowUserManager.setCurrentThreadUser(currentUser.getUsername());
            }

            if (!"/WEB-INF/jsp/unauthorized.jsp".equals(request.getServletPath())) {
                LogUtil.info(getClass().getName(), "Authentication for user " + ((loginAs == null) ? username : loginAs) + ": " + true);
                WorkflowHelper workflowHelper = (WorkflowHelper) AppUtil.getApplicationContext().getBean("workflowHelper");
                workflowHelper.addAuditTrail("WorkflowHttpAuthProcessingFilter", "authenticate", "Authentication for user " + ((loginAs == null) ? username : loginAs) + ": " + true);
            }
        } else {
            if (us != null && us.getAuthenticateAllApi()) {
                throw new BadCredentialsException("");
            }
        }

        return auth;
    }
   
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException, ServletException {
        String uri = request.getRequestURI();
        if (!uri.startsWith(request.getContextPath() + "/j_spring_security_check")) {
            // set temporary per-request authentication
            SecurityContextHolder.getContext().setAuthentication(authResult);
            // clear system alert
            AppUtil.getSystemAlert();
        } else {
            TargetUrlResolver resolver = getTargetUrlResolver();
                   
            if (resolver instanceof TargetUrlResolverImpl) {
                ((TargetUrlResolverImpl)resolver).setJustUseSavedRequestOnGet(true);
            }
           
            HttpSession session = request.getSession(false);
            if (session != null) {
                SavedRequest savedRequest = (SavedRequest) session.getAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY);
            }
            // default spring security login
            super.successfulAuthentication(request, response, authResult);
        }
    }
   
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException ae) throws IOException, ServletException {
        String uri = request.getRequestURI();
        if (uri.startsWith(request.getContextPath() + "/web/json/")) {
            // return 401 for unauthorized JSON API calls
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } else {
            super.unsuccessfulAuthentication(request, response, ae);
        }
    }   
   
    public WorkflowUserManager getWorkflowUserManager() {
        return workflowUserManager;
    }

    public void setWorkflowUserManager(WorkflowUserManager workflowUserManager) {
        this.workflowUserManager = workflowUserManager;
    }

    public DirectoryManager getDirectoryManager() {
        return directoryManager;
    }

    public void setDirectoryManager(DirectoryManager directoryManager) {
        this.directoryManager = directoryManager;
    }

    public SetupManager getSetupManager() {
        return setupManager;
    }

    public void setSetupManager(SetupManager setupManager) {
        this.setupManager = setupManager;
    }
   
    public LocaleResolver getLocaleResolver() {
        return localeResolver;
    }

    public void setLocaleResolver(LocaleResolver localeResolver) {
        this.localeResolver = localeResolver;
    }
}
TOP

Related Classes of org.joget.apps.workflow.security.WorkflowHttpAuthProcessingFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.