Package com.adito.security.actions

Source Code of com.adito.security.actions.LogonAction

package com.adito.security.actions;

import java.util.List;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import com.adito.boot.ContextKey;
import com.adito.boot.KeyStoreManager;
import com.adito.core.BundleActionMessage;
import com.adito.core.CoreAttributeConstants;
import com.adito.core.CoreEvent;
import com.adito.core.CoreEventConstants;
import com.adito.core.CoreException;
import com.adito.core.CoreServlet;
import com.adito.core.GlobalWarning;
import com.adito.core.GlobalWarningManager;
import com.adito.core.RedirectWithMessages;
import com.adito.core.RequestParameterMap;
import com.adito.core.ServletRequestAdapter;
import com.adito.core.GlobalWarning.DismissType;
import com.adito.policyframework.PolicyDatabaseFactory;
import com.adito.policyframework.PolicyUtil;
import com.adito.properties.Property;
import com.adito.properties.impl.profile.ProfilePropertyKey;
import com.adito.properties.impl.systemconfig.SystemConfigKey;
import com.adito.properties.impl.userattributes.UserAttributeKey;
import com.adito.security.AccountLockedException;
import com.adito.security.AuthenticationModule;
import com.adito.security.AuthenticationScheme;
import com.adito.security.Constants;
import com.adito.security.Credentials;
import com.adito.security.InputRequiredException;
import com.adito.security.InvalidLoginCredentialsException;
import com.adito.security.LogonController;
import com.adito.security.LogonControllerFactory;
import com.adito.security.LogonStateAndCache;
import com.adito.security.PasswordCredentials;
import com.adito.security.SessionInfo;
import com.adito.security.User;
import com.adito.security.forms.LogonForm;

/**
* Logs a user into the Adito.
*
* @author Lee David Painter
*/
public class LogonAction extends Action {

    private static Log log = LogFactory.getLog(LogonAction.class);

    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
                    throws Exception {

        ActionMessages msgs = new ActionMessages();

        SessionInfo sessionInfo = LogonControllerFactory.getInstance().getSessionInfo(request);
       
        if (sessionInfo == null && request.getSession().getAttribute(Constants.SESSION_LOCKED) == null
                        && LogonControllerFactory.getInstance().hasClientLoggedOn(request, response) == LogonController.LOGGED_ON) {
            if (log.isDebugEnabled())
                log.debug(request.getRemoteHost() + " is already authenticated");

            return mapping.findForward("success");
        }
       
        /*
         * Get the authentication session and module to use to validate this
         * authentication attempt
         */
        AuthenticationScheme scheme = (AuthenticationScheme) request.getSession().getAttribute(Constants.AUTH_SESSION);
        LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
                        LogonStateAndCache.LOGON_STATE_MACHINE);

        // there are different users so we need to logon again, clearing the authentication scheme and logon machine.
        if (sessionInfo != null && logonStateMachine != null && !sessionInfo.getUser().equals(logonStateMachine.getUser())){
            request.getSession().removeAttribute(Constants.AUTH_SESSION);
            request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
            LogonControllerFactory.getInstance().logoffSession(request, response);
            msgs.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed", "Session no longer valid, logon again."));
            saveErrors(request, msgs);
            return new RedirectWithMessages(mapping.findForward("logon"), request);
        }
       
        if (logonStateMachine == null) {
            logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_STARTED, request.getSession());
            request.getSession().setAttribute(LogonStateAndCache.LOGON_STATE_MACHINE, logonStateMachine);
        }
        if (scheme == null) {

            ActionForward fwd = null;
            try {
                fwd = ShowLogonAction.checkAuthSession(null, false, mapping, request, response, logonStateMachine);
            } catch(CoreException ce) {
             
            } catch (Throwable e) {
                log.error("Logon not allowed.", e);
                ActionMessages errs = new ActionMessages();
                if(e instanceof CoreException) {
                  errs.add(Globals.ERROR_KEY, ((CoreException)e).getBundleActionMessage());
                }
                else {
                  errs.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed",
                                  "Please contact your administrator."));
                }
                saveErrors(request, errs);
                request.getSession().removeAttribute(Constants.AUTH_SESSION);
                request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
                if (form != null)
                    form.reset(mapping, request);
                return new RedirectWithMessages(mapping.findForward("failed"), request);
            }
            if (fwd != null) {
                scheme = (AuthenticationScheme) request.getSession().getAttribute(Constants.AUTH_SESSION);
            }
        }

        if (scheme != null) {
            AuthenticationModule module = scheme.currentAuthenticationModule();
            if (module == null) {
                log.error("No authentication module.");
                request.getSession().removeAttribute(Constants.AUTH_SESSION);
                return mapping.findForward("logon");
            }

            try {             
              // If there is no user in the scheme then it is an invalid login
              if(scheme.getUser() == null) {
                throw new InvalidLoginCredentialsException();
              }
             
              // Check the account is enabled and not locked
              if(!PolicyUtil.isEnabled(scheme.getUser())) {
                throw new AccountLockedException(scheme.getUsername(), "Account disabled.", true, 0);
              }
             
              // Check for locks
              LogonControllerFactory.getInstance().checkForAccountLock(scheme.getUsername(), scheme.getUser().getRealm().getResourceName());

              // Authenticate
                authenticate(scheme, request);

                // Check logon is currently allowed
                String logonNotAllowedReason = LogonControllerFactory.getInstance().checkLogonAllowed(
                                scheme.getUser());

                if (logonNotAllowedReason != null) {
                    log.warn("Logon not allowed because '" + logonNotAllowedReason + "'");
                    msgs.add(Globals.ERROR_KEY, new ActionMessage("login.logonNotAllowed", logonNotAllowedReason));
                    saveErrors(request, msgs);
                    return new RedirectWithMessages(mapping.findForward("logon"), request);
                }

                // Check for the next authentication modules
                AuthenticationModule nextModule = scheme.nextAuthenticationModule();
                if (nextModule != null && request.getSession().getAttribute(Constants.SESSION_LOCKED) == null) {
                    if (log.isDebugEnabled())
                        log.debug("There are more authentication modules to satisfy (current mapping = " + mapping.getPath());
                    ActionForward fw = new RedirectWithMessages(mapping.findForward("logon"), request);
                    return fw;
                }

                return finishAuthentication(scheme, request, response);
            } catch (InputRequiredException ex) {
                // The page wants to display or redirect somewhere
              if(ex.getForward()==null)
                return mapping.findForward("logon");
              else
                return ex.getForward();
            } catch (AccountLockedException ale) {
                return accountLocked(mapping, request, ale, msgs);
            } catch (InvalidLoginCredentialsException ex) {
                log.error("[" + request.getRemoteHost()
                    + "] authentication failed", ex);

                LogonForm logonForm = (LogonForm) form;

                CoreServlet.getServlet().fireCoreEvent(
                    new CoreEvent(this, CoreEventConstants.LOGON, null, null, ex).addAttribute(
                        CoreAttributeConstants.EVENT_ATTR_IP_ADDRESS, request.getRemoteAddr()).addAttribute(
                        CoreAttributeConstants.EVENT_ATTR_HOST, request.getRemoteHost()).addAttribute(
                        CoreAttributeConstants.EVENT_ATTR_SCHEME, scheme.getSchemeName()).addAttribute(
                        CoreAttributeConstants.EVENT_ATTR_ACCOUNT, logonForm.getUsername()));

               
              request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
                request.getSession().removeAttribute(Constants.AUTH_SESSION);

                try {
                    scheme.setAccountLock(LogonControllerFactory.getInstance().logonFailed(((LogonForm)form).getUsername(),
                                    ((LogonForm)form).getRealmName(), scheme.getAccountLock()));
                } catch (AccountLockedException ale) {
                  return accountLocked(mapping, request, ale, msgs);
                }

                msgs.add(Globals.ERROR_KEY, new ActionMessage("login.invalidCredentials"));
                saveErrors(request, msgs);
                return new RedirectWithMessages(mapping.findForward("logon"), request);
            } catch (Exception e) {
                log.error("Internal error authenticating.", e);
                msgs.add(Globals.ERROR_KEY, new BundleActionMessage("security", "login.error", e.getMessage()));
                saveErrors(request, msgs);
                request.getSession().setAttribute(Constants.EXCEPTION, e);
              request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
                request.getSession().removeAttribute(Constants.AUTH_SESSION);
                return new RedirectWithMessages(mapping.findForward("logon"), request);
            }
        } else {
            ActionMessages errs = new ActionMessages();
            errs.add(Globals.MESSAGE_KEY, new BundleActionMessage("security", "login.logonNotAllowed", "No scheme available."));
            saveErrors(request, errs);
            request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
            request.getSession().removeAttribute(Constants.AUTH_SESSION);
            if (form != null)
                form.reset(mapping, request);
            return new RedirectWithMessages(mapping.findForward("logon"), request);
        }
    }

    /**
     * Complete the authentication process.
     *
     * @param scheme scheme
     * @param request request
     * @param response response
     * @return forward to
     * @throws Exception on any error
     */
    public static ActionForward finishAuthentication(AuthenticationScheme scheme, HttpServletRequest request,
                    HttpServletResponse response) throws Exception {

        // Check we have a user object
        if (scheme.getUser() == null) {
            throw new Exception("No authentication module provided a user.");
        }

        // now add the policies associated with this scheme to the http session
        // if the property says so.
        if (Property.getPropertyBoolean(new SystemConfigKey("security.enforce.policy.resource.access"))) {
            List signOnPolicies = PolicyDatabaseFactory.getInstance().getPoliciesAttachedToResource(scheme,
                            scheme.getUser().getRealm());
            scheme.getServletSession().setAttribute("auth.scheme.policies", signOnPolicies);
        }

        // If the user is a manager, check if there is a new Adito
        // version, or if there any exension updates
        if (PolicyDatabaseFactory.getInstance().isAnyAccessRightAllowed(scheme.getUser(), true, true, false)) {
           
            if ("false".equals(Property.getProperty(new ContextKey("webServer.disableCertificateWarning")))
                            && !KeyStoreManager.getInstance(KeyStoreManager.DEFAULT_KEY_STORE).isCertificateTrusted(
                                            Property.getProperty(new ContextKey("webServer.alias")))) {
                GlobalWarningManager.getInstance().addMultipleGlobalWarning(new GlobalWarning(GlobalWarning.MANAGEMENT_USERS, new BundleActionMessage("keystore",
                    "keyStore.untrustedCertificate.warning"), DismissType.DISMISS_FOR_USER));
            }
           
        }

        /*
         * Each authentication module needs to be informed that authentication
         * is now complete so it may perform any last minute checks
         */
        scheme.authenticationComplete(request, response);

        // Allow the home page to be redirected.
        request.getSession().setAttribute(Constants.REDIRECT_HOME, "true");

        // Authenitcation sequence complete
        if (log.isDebugEnabled())
            log.debug(scheme.getUsername() + " [" + request.getRemoteHost() + "] has been authenticated");

        // Forward control to the specified success URI (possibly from the
        // initial unautenticated request)
        String originalRequest = (String) request.getSession().getAttribute(Constants.ORIGINAL_REQUEST);
        ActionForward forward = null;

        // Where next?
        List profiles = (List)request.getSession().getAttribute(Constants.PROFILES);
        int selectProfileAtLogin = -1;
        try {
          selectProfileAtLogin = Property.getPropertyInt(new UserAttributeKey(scheme.getUser(),  User.USER_STARTUP_PROFILE));
        }
        catch(NumberFormatException nfe) {
        }
        if (selectProfileAtLogin == -1 && profiles != null && profiles.size() > 1) {
            // Prompt for the profile
            forward = new ActionForward("/showSelectPropertyProfile.do");
        } else {
            if(null == originalRequest || "/showHome.do".equals(originalRequest) || "".equals(originalRequest)) {
                boolean admin = LogonControllerFactory.getInstance().isAdministrator(scheme.getUser());
                if (admin) {
                    originalRequest = "/showSystemConfiguration.do";
                } else {
                    originalRequest = "/showHome.do";
                }
                request.getSession().removeAttribute(Constants.ORIGINAL_REQUEST);
            }
            if (Property.getPropertyBoolean(new ProfilePropertyKey("client.autoStart", LogonControllerFactory.getInstance().getSessionInfo(request)))) {
                request.getSession().removeAttribute(Constants.ORIGINAL_REQUEST);
                request.getSession().setAttribute(Constants.REQ_ATTR_LAUNCH_AGENT_REFERER, originalRequest);
                forward = new ActionForward("/launchAgent.do", false);
            } else {
                forward = new ActionForward(originalRequest, true);
            }
        }
        return forward;

    }

    /**
     * Start the authentication process.
     *
     * @param scheme scheme
     * @param request request
     * @throws Exception on any error
     */
    public static void authenticate(AuthenticationScheme scheme, HttpServletRequest request) throws Exception {
        AuthenticationModule module = scheme.currentAuthenticationModule();
        if (module == null) {
            throw new Exception("No current authentication module");
        }
        RequestParameterMap params = new RequestParameterMap(new ServletRequestAdapter(request));
        User currentUser = scheme.getUser();
        LogonStateAndCache logonStateMachine = (LogonStateAndCache) request.getSession().getAttribute(
                        LogonStateAndCache.LOGON_STATE_MACHINE);

        if (logonStateMachine == null) {
            logonStateMachine = new LogonStateAndCache(LogonStateAndCache.STATE_STARTED, request.getSession());
        }

        if (logonStateMachine.getState() == LogonStateAndCache.STATE_KNOWN_USERNAME_NO_SCHEME_SPOOF_PASSWORD_ENTRY) {
            scheme.addCredentials(new PasswordCredentials("", "".toCharArray()));
        } else if (logonStateMachine.getState() == LogonStateAndCache.STATE_UNKNOWN_USERNAME_PROMPT_FOR_PASSWORD) {
            Credentials creds = module.authenticate(request, params);
            if(creds!=null)
              scheme.addCredentials(creds);
        } else {
          Credentials creds = module.authenticate(request, params);
            if(creds!=null) {
              scheme.addCredentials(creds);
              logonStateMachine.setState(LogonStateAndCache.STATE_VALID_LOGON);
            }
            // Check we have a user object
            if (currentUser == null && scheme.getUser() == null) {
                throw new Exception("The first authentication did not provide a user.");
            }
        }

        PolicyUtil.checkLogin(scheme.getUser());
    }

  /**
   * Set an account to be locked and create the appropriate error messages
   *
   * @param mapping mapping
   * @param request request
   * @param ale lock exception
   * @param msgs messages
   * @return forward
   */
  ActionForward accountLocked(ActionMapping mapping, HttpServletRequest request, AccountLockedException ale,
                        ActionMessages msgs) {

    request.getSession().removeAttribute(Constants.AUTH_SESSION);
    request.getSession().removeAttribute(LogonStateAndCache.LOGON_STATE_MACHINE);
    msgs.add(Globals.ERROR_KEY, new ActionMessage(ale.isDisabled() ? "login.accountDisabled" : "login.accountLocked",
            String.valueOf(((ale.getTimeLeft() / 1000) + 59) / 60)));
    log.warn(ale.getUsername() + " [" + request.getRemoteHost() + "] account locked", ale);
    saveErrors(request, msgs);
    return new RedirectWithMessages(mapping.findForward("logon"), request);
  }

}
TOP

Related Classes of com.adito.security.actions.LogonAction

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.