org.apache.directory.fortress.web.control.SecUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.directory.fortress.web.control.SecUtils.java

Source

/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */
package org.apache.directory.fortress.web.control;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.fortress.core.*;
import org.apache.directory.fortress.core.SecurityException;
import org.apache.directory.fortress.core.util.Config;
import org.apache.directory.fortress.core.model.UserRole;
import org.apache.directory.fortress.core.model.Warning;
import org.apache.directory.fortress.realm.*;
import org.apache.directory.fortress.realm.GlobalIds;
import org.apache.log4j.Logger;
import org.apache.wicket.Component;
import org.apache.directory.fortress.core.model.Permission;
import org.apache.directory.fortress.core.model.Session;
import org.apache.directory.fortress.core.model.User;
import org.apache.wicket.ajax.AjaxRequestTarget;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.List;

/**
 * Common static utils and wrappers used by Wicket web apps to make fortress style security calls.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 */
public class SecUtils {
    private static final Logger LOG = Logger.getLogger(SecUtils.class.getName());
    private static final String PERMS_CACHED = "perms.cached";
    public static final boolean IS_PERM_CACHED = ((Config.getInstance().getProperty(PERMS_CACHED) != null)
            && (Config.getInstance().getProperty(PERMS_CACHED).equalsIgnoreCase("true")));

    /**
     * Return the fortress session that is cached within the wicket session object.
     *
     * @param component needed to get handle to wicket session.
     * @return fortress session object.
     */
    public static Session getSession(Component component) {
        return ((WicketSession) component.getSession()).getSession();
    }

    /**
     *  Used when web app needs to create a 'trusted' fortress session.
     *
     *  Does not check user's password.
     *
     * @param accessMgr fortress access mgr apis
     * @param userId required for rbac session creation.
     * @return rbac session.
     */
    public static Session createSession(AccessMgr accessMgr, String userId) {
        Session session;
        try {
            // Create an RBAC session and attach to Wicket session:
            session = accessMgr.createSession(new User(userId), true);
            String message = "RBAC Session successfully created for userId: " + session.getUserId();
            LOG.debug(message);
        } catch (org.apache.directory.fortress.core.SecurityException se) {
            String error = "createSession caught SecurityException=" + se;
            LOG.error(error);
            throw new RuntimeException(error);
        }
        return session;
    }

    /**
     * Here the wicket session is loaded with the fortress session and permissions.
     *
     *
     * @param delAccessMgr needed to pull back fortress arbac permissions.
     * @param session needed for call into accessMgr.
     */
    public static void loadPermissionsIntoSession(DelAccessMgr delAccessMgr, Session session) {
        try {
            // Retrieve user permissions and attach fortress session to Wicket session:
            ((WicketSession) WicketSession.get()).setSession(session);
            List<Permission> permissions = delAccessMgr.sessionPermissions(session);
            ((WicketSession) WicketSession.get()).setPermissions(permissions);
            String message = "Session successfully created for userId: " + session.getUserId();
            LOG.debug(message);
        } catch (org.apache.directory.fortress.core.SecurityException se) {
            String error = "loadPermissionsIntoSession caught SecurityException=" + se;
            LOG.error(error);
            throw new RuntimeException(error);
        }
    }

    /**
     * Returns the fortress arbac perms that are cashed in the wicket session.
     *
     * @param component needed to get a handle on the wicket session object.
     * @return collection of fortress admin perms.
     */
    public static List<Permission> getPermissions(Component component) {
        return ((WicketSession) component.getSession()).getPermissions();
    }

    /**
     * Retrieve RBAC session permissions from Fortress and place in the Wicket session.
     */
    public static void getPermissions(Component component, AccessMgr accessMgr) {
        try {
            if (IS_PERM_CACHED) {
                WicketSession session = (WicketSession) component.getSession();
                List<Permission> permissions = accessMgr.sessionPermissions(session.getSession());
                ((WicketSession) WicketSession.get()).setPermissions(permissions);
            }
        } catch (org.apache.directory.fortress.core.SecurityException se) {
            String error = "getPermissions caught SecurityException=" + se;
            LOG.error(error);
            throw new RuntimeException(error);
        }
    }

    /**
     * Wrapper for the httpservlet isUserInRole api.
     *
     * @param roleName contains the name of role being checked.
     * @param servletReq handle used to make inquiry.
     * @return true if authorized, false otherwise.
     */
    public static boolean isAuthorized(String roleName, HttpServletRequest servletReq) {
        boolean isAuthorized = false;
        if (servletReq.isUserInRole(roleName)) {
            isAuthorized = true;
        }
        return isAuthorized;
    }

    /**
     * Is the supplied permission in the wicket session cache?  Called by buttons.
     * if not found, button will be invisible.
     *
     * @param permission fortress perm requires {link @Permission#objName} and {link @Permission#opName} are set.
     * @param component needed to get handle on the wicket session object.
     * @return true if found, false otherwise
     */
    public static boolean isFound(Permission permission, Component component) {
        List<Permission> permissions = SecUtils.getPermissions(component);
        return CollectionUtils.isNotEmpty(permissions) && permissions.contains(permission);
    }

    /**
     * Wrapper to fortress checkAccess api.
     *
     * @param component contains the wicket session handle.
     * @param accessMgr has the checkAccess api
     * @param objName string value
     * @param opName string value
     * @param objId string value
     * @return true if success, false otherwise.
     * @throws org.apache.directory.fortress.core.SecurityException checked exception for system errors.
     */
    public static boolean checkAccess(Component component, AccessMgr accessMgr, String objName, String opName,
            String objId) throws org.apache.directory.fortress.core.SecurityException {
        WicketSession session = (WicketSession) component.getSession();
        Permission permission = new Permission(objName, opName, objId);
        return accessMgr.checkAccess(session.getSession(), permission);
    }

    /**
     * Convert the principal into fortress session and load into wicket session along with perms.
     *
     * @param component contains handle to wicket session.
     * @param j2eePolicyMgr used to call deserize api
     * @param accessMgr used to call fortress api for role op
     * @param szPrincipal contains the instance of fortress session deserialized.
     */
    public static void initializeSession(Component component, J2eePolicyMgr j2eePolicyMgr, AccessMgr accessMgr,
            String szPrincipal) throws SecurityException {
        Session realmSession = null;

        if (j2eePolicyMgr == null || accessMgr == null) {
            throw new SecurityException(GlobalIds.SESSION_INITIALIZATION_FAILED,
                    "initializeSession failed - verify the injection of fortress spring beans into your application");
        }
        try {
            if (StringUtils.isNotEmpty(szPrincipal))
                realmSession = j2eePolicyMgr.deserialize(szPrincipal);
        } catch (SecurityException se) {
            throw new RuntimeException(se);
        }
        if (realmSession != null) {
            synchronized ((WicketSession) WicketSession.get()) {
                if (SecUtils.getSession(component) == null) {
                    LOG.info("realmSession user: " + realmSession.getUserId());
                    // Retrieve user permissions and attach RBAC session to Wicket session:
                    ((WicketSession) WicketSession.get()).setSession(realmSession);
                    getPermissions(component, accessMgr);
                }
            }
        }
    }

    /**
     * Call RBAC addActiveRole to activate a new role into user's session.
     * This routine must first retrieves the wicket session.
     * It is needed because it contains the fortress session which is required for api.
     * Next it invokes the fortress addActiveRole method.
     * If all successful refresh user's perms cached as they've changed.
     *
     * @param component contains handle to wicket session.
     * @param target used to display modal if something goes wrong
     * @param accessMgr used to call fortress api for role op
     * @param roleName contains the role name target
     * @return true if success, false otherwise.
     */
    public static boolean addActiveRole(Component component, AjaxRequestTarget target, AccessMgr accessMgr,
            String roleName) {
        boolean isSuccessful = false;
        try {
            WicketSession session = (WicketSession) component.getSession();
            session.getSession().setWarnings(null);
            accessMgr.addActiveRole(session.getSession(), new UserRole(roleName));
            List<Warning> warnings = session.getSession().getWarnings();
            if (CollectionUtils.isNotEmpty(warnings)) {
                for (Warning warning : warnings) {
                    LOG.info("Warning: " + warning.getMsg() + " errCode: " + warning.getId() + " name: "
                            + warning.getName() + " type: " + warning.getType().toString());
                    if (warning.getType() == Warning.Type.ROLE && warning.getName().equalsIgnoreCase(roleName)) {
                        String error = warning.getMsg() + " code: " + warning.getId();
                        LOG.error(error);
                        target.appendJavaScript(";alert('" + error + "');");
                        return false;
                    }
                }
            }

            // User's active role set changed so refresh their permissions:
            SecUtils.getPermissions(component, accessMgr);
            isSuccessful = true;
            String message = "Activate role name: " + roleName + " successful";
            LOG.info(message);
        } catch (org.apache.directory.fortress.core.SecurityException se) {
            String msg = "Role selection " + roleName + " activation failed because of ";
            if (se.getErrorId() == GlobalErrIds.DSD_VALIDATION_FAILED) {
                msg += "Dynamic SoD rule violation";
            } else if (se.getErrorId() == GlobalErrIds.URLE_ALREADY_ACTIVE) {
                msg += "Role already active in Session";
            } else {
                msg += "System error: " + se + ", " + "errId=" + se.getErrorId();
            }
            LOG.error(msg);
            target.appendJavaScript(";alert('" + msg + "');");
        }
        return isSuccessful;
    }

    /**
     * Call RBAC dropActiveRole to deactivate a new role from user's session.
     * This routine must first retrieves the wicket session.
     * It is needed because it contains the fortress session which is required for api.
     * Next it invokes the fortress dropActiveRole method.
     * If all successful refresh user's perms cached as they've changed.
     *
     * @param component contains handle to wicket session.
     * @param target used to display modal if something goes wrong
     * @param accessMgr used to call fortress api for role op
     * @param roleName contains the role name target
     * @return true if success, false otherwise.
     */
    public static boolean dropActiveRole(Component component, AjaxRequestTarget target, AccessMgr accessMgr,
            String roleName) {
        boolean isSuccessful = false;
        try {
            WicketSession session = (WicketSession) component.getSession();
            accessMgr.dropActiveRole(session.getSession(), new UserRole(roleName));
            // User's active role set changed so refresh their permissions:
            SecUtils.getPermissions(component, accessMgr);
            isSuccessful = true;
            LOG.info("Fortress dropActiveRole roleName: " + roleName + " was successful");
        } catch (SecurityException se) {
            String msg = "Role selection " + roleName + " deactivation failed because of ";
            if (se.getErrorId() == GlobalErrIds.URLE_NOT_ACTIVE) {
                msg += "Role not active in session";
            } else {
                msg += "System error: " + se + ", " + "errId=" + se.getErrorId();
            }
            LOG.error(msg);
            target.appendJavaScript(";alert('" + msg + "');");
        }
        return isSuccessful;
    }

    /**
     * Enables fortress session on behalf of a java.security.Principal retrieved from the container.
     *
     * @param component
     * @param servletReq
     * @param j2eePolicyMgr
     * @param accessMgr
     * @throws SecurityException
     */
    public static void enableFortress(Component component, HttpServletRequest servletReq,
            J2eePolicyMgr j2eePolicyMgr, AccessMgr accessMgr) throws SecurityException {
        // Get the principal from the container:
        Principal principal = servletReq.getUserPrincipal();
        // Is this a Java EE secured page && has the User successfully authenticated already?
        boolean isSecured = principal != null;
        if (isSecured) {
            //linksLabel += " for " + principal.getName();
            if (!isLoggedIn(component)) {
                String szPrincipal = principal.toString();
                // Pull the fortress session from the realm and assert into the Web app's session along with user's perms:
                SecUtils.initializeSession(component, j2eePolicyMgr, accessMgr, szPrincipal);
            }
        }
    }

    /**
     * If user has a wicket session then considered logged in.
     *
     * @return true if wicket session is not null
     */
    public static boolean isLoggedIn(Component component) {
        boolean isLoggedIn = false;
        if (getSession(component) != null) {
            isLoggedIn = true;
        }
        return isLoggedIn;
    }

    public static Permission getPermFromId(String id) {
        Permission perm = null;
        String[] parts = id.split("\\.");
        if (parts.length > 1) {
            String objName = parts[0];
            String opName = parts[1];
            perm = new Permission(objName, opName);
        }
        return perm;
    }

}