All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.evasion.sam.SAM Maven / Gradle / Ivy

There is a newer version: 2.0.0.2
Show newest version
package com.evasion.sam;

import com.evasion.sam.ejb.JNDIClient;
import com.evasion.sam.ejb.JaasEjb;
import com.evasion.sam.jaas.EvasionGroup;
import com.evasion.sam.jaas.EvasionPrincipal;
import java.io.IOException;
import java.security.Principal;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.message.AuthException;
import javax.security.auth.message.AuthStatus;
import javax.security.auth.message.MessageInfo;
import javax.security.auth.message.MessagePolicy;
import javax.security.auth.message.callback.CallerPrincipalCallback;
import javax.security.auth.message.callback.GroupPrincipalCallback;
import javax.security.auth.message.module.ServerAuthModule;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

/**
 *
 *
 * @author nasradu8
 */
public class SAM implements ServerAuthModule {

    private static final Logger LOGGER = Logger.getLogger(SAM.class.getName());

    private static final String SAVED_SUBJECT = "Saved_Subject";

    private static final String USER_NAME = "userName";

    private static final String KEY_EVASION_SAVED_REQUEST_URL = "javax.security.evasion.SavedRequestURL";

    private CallbackHandler handler;

    private Config config = new Config();

    protected static final Class[] SUPPORTED_MESSAGE_TYPES = new Class[]{
        javax.servlet.http.HttpServletRequest.class,
        javax.servlet.http.HttpServletResponse.class
    };

    private String lcName = null;

    private JaasEjb loginEJB = null;

    private LoginContext lc = null;

    private MyCBH cbh = null;

    JNDIClient ejbClient = null;

    private String loginURI;

    @Override
    public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException {
        LOGGER.finer("Init SAM");
        if (options != null) {
            config.setJndi((String) options.get(Config.PARAM_EJB_JNDI));
            config.setProviderUrl((String) options.get(Config.PARAM_PROVIDER_URL));
            config.setDigestAlgorithm((String) options.get(Config.PARAM_DIGEST_ALGORITHM));
            LOGGER.log(Level.FINER, "SAM mandatory : {0}", requestPolicy.isMandatory());
            this.loginURI = (String) options.get(Constants.LOGIN_URL);
            this.handler = handler;
            this.lcName = (String) options.get(Constants.LOGIN_CONTEXT_IMPL);
            LOGGER.log(Level.FINE, "Login Context Name:{0}", this.lcName);
        }
        try {
            getLc();
            ejbClient = new JNDIClient(config.getProviderUrl());
            loginEJB = (JaasEjb) ejbClient.lookup(config.getJndi());
        } catch (LoginException ex) {
            LOGGER.log(Level.SEVERE, "Exception d''init SAM{0}", ex.toString());
            AuthException ae = new AuthException();
            ae.initCause(ex);
            throw ae;
        }
    }

    @Override
    public Class[] getSupportedMessageTypes() {
        return SUPPORTED_MESSAGE_TYPES.clone();
    }

    @Override
    public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
        HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
        HttpServletResponse response = (HttpServletResponse) (messageInfo.getResponseMessage());

        LOGGER.log(Level.FINER, "ValidateRequest: {0}", request.getRequestURL().toString());
        // Vérification si authentification déjà validé
        HttpSession session = request.getSession(true);
        if (request.getRequestURI().contains(Constants.PATH_SECURITY_LOGOUT)) {
            LOGGER.finer("Logout request.");
            response.setHeader("Location", response.encodeRedirectURL(request.getContextPath() + "/"));
            response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
            session.invalidate();
            return AuthStatus.SEND_SUCCESS;
        }

        Subject savedClientSubject = (Subject) session.getAttribute(SAVED_SUBJECT);
        if (savedClientSubject != null) {
            clientSubject.getPrincipals().addAll(savedClientSubject.getPrincipals());
            clientSubject.getPublicCredentials().addAll(savedClientSubject.getPublicCredentials());
            clientSubject.getPrivateCredentials().addAll(savedClientSubject.getPrivateCredentials());
            return AuthStatus.SUCCESS;
        }


        if (!isMandatory(messageInfo) && !request.getRequestURI().contains(Constants.PATH_SECURITY_CHECK)) {
            return AuthStatus.SUCCESS;

        }


        // See if the username / password has been passed in...
        String username = request.getParameter("j_username");
        String password = request.getParameter("j_password");
        String backward = request.getParameter("j_backward");
        LOGGER.log(Level.FINE, "Form param: {0} {1} {2}", new Object[]{username, password, request.getMethod()});
        if ((username == null) || (password == null)) { // @TODO à remettre || !request.getMethod().equalsIgnoreCase("post")) {
            // Not passed in, show the login page...
            //RequestDispatcher rd = request.getRequestDispatcher(this.loginURI);
            try {
                response.setHeader("Location", response.encodeRedirectURL(request.getContextPath() + this.loginURI));
                response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
                //    rd.forward(request, response);
            } catch (Exception ex) {
                AuthException ae = new AuthException();
                ae.initCause(ex);
                throw ae;
            }
            return AuthStatus.SEND_CONTINUE;
        }


        // Check to see if successfull
        try {
            cbh.setRequest(request);
            lc.login();
            LOGGER.fine("Traitement du formulaire d'authentification");
            clientSubject = lc.getSubject();
            setCallerPrincipal(clientSubject);

            // recreate the session
            Map map = new HashMap();
            Enumeration names = session.getAttributeNames();
            while (names.hasMoreElements()) {
                String key = names.nextElement();
                map.put(key, session.getAttribute(key));
            }
            session.invalidate();
            session = request.getSession(true);
            for (Entry key : map.entrySet()) {
                session.setAttribute(key.getKey().toString(), key.getValue());
            }

            // Save the Subject...
            session.setAttribute(SAVED_SUBJECT, clientSubject);

            // Save the userName
            session.setAttribute(USER_NAME, username);

            try {
                // Redirect...
                if (getSavedRequestURL(session) != null) {
                    response.sendRedirect(response.encodeRedirectURL(getSavedRequestURL(session)));
                } else if (backward != null) {
                    response.sendRedirect(response.encodeRedirectURL(backward));
                } else {
                    response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + "/"));
                }
            } catch (Exception ex) {
                AuthException ae = new AuthException();
                ae.initCause(ex);
                throw ae;
            }

            /*
             * if ((new Date().getTime() - ((EvasionPrincipal)
             * userPrincipal).getLastLogin().getTime()) > 86400) {
             * UserTransaction tx = ejbClient.getTransaction(); if (tx != null)
             * { LOGGER.log(Level.FINE, "UserTransaction status
             * {0}",tx.getStatus()); tx.begin(); try {
             * loginEJB.postLogin(userPrincipal.getName()); } finally {
             * tx.commit(); tx = null; } } }
             */
            saveLoginBackToURL(request, session);

            // Continue...
            return AuthStatus.SEND_CONTINUE;

        } catch (LoginException le) {
            LOGGER.log(Level.SEVERE, "ERROR SAM!!!", le);
            RequestDispatcher rd = request.getRequestDispatcher(this.loginURI);
            try {
                rd.forward(request, response);
            } catch (Exception ex) {
                AuthException ae = new AuthException();
                ae.initCause(ex);
                throw ae;
            }
            return AuthStatus.SEND_FAILURE;
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, "ERROR SAM!!!", ex);
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            } catch (IOException ex1) {
                Logger.getLogger(SAM.class.getName()).log(Level.SEVERE, null, ex1);
            }
            return AuthStatus.SEND_FAILURE;
        }
    }

    private void setCallerPrincipal(Subject clientSubject) throws AuthException {
        boolean assignGroups = true;
        List groups = new ArrayList();
        Principal userPrincipal = null;
        String[] assignedGroups = null;
        for (Principal p : clientSubject.getPrincipals()) {
            String tmp = p.getName();
            LOGGER.log(Level.FINE, "Principal utilis\u00e9: {0}", tmp);
            if (p instanceof EvasionGroup && "Roles".equals(tmp)) {

                EvasionGroup evasionGroup = (EvasionGroup) p;

                for (Principal grp : Collections.list(evasionGroup.members())) {
                    groups.add(grp.getName());
                    LOGGER.log(Level.FINE, "Groupe associe: {0}", grp.getName());

                }
                assignedGroups = new String[groups.size()];
                assignedGroups = groups.toArray(assignedGroups);
            } else {
                userPrincipal = p;
            }
        }

        CallerPrincipalCallback callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, userPrincipal);

        if (callerPrincipalCallback.getName() == null && callerPrincipalCallback.getPrincipal() == null) {
            assignGroups = false;
        }
        try {
            handler.handle((assignGroups ? new Callback[]{
                        callerPrincipalCallback,
                        new GroupPrincipalCallback(callerPrincipalCallback.getSubject(),
                        assignedGroups)} : new Callback[]{callerPrincipalCallback}));

            LOGGER.log(Level.FINE, "jmac.caller_principal:{0} {1}", new Object[]{callerPrincipalCallback.getName(), callerPrincipalCallback.getPrincipal()});
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, "ERROR SAM!!!", ex);
            AuthException ae = new AuthException();
            ae.initCause(ex);
            throw ae;
        }
    }

    @Override
    public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
        HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
        clearSavedRequestURLs(request);
        clearPrincipals(request);
        //Remove Principals from Subject.
        subject.getPrincipals().clear();
        subject.getPrivateCredentials().clear();
        subject.getPublicCredentials().clear();

        try {
            lc.logout();
        } catch (LoginException ex) {
            AuthException ae = new AuthException();
            ae.initCause(ex);
            throw ae;
        }
    }

    /**
     * Remove saved request URLs from session to avoid mixing up resources from
     * previous operations (logins, logouts) with the current one.
     *
     * @param session Our current session
     */
    protected void clearSavedRequestURLs(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute(KEY_EVASION_SAVED_REQUEST_URL);
        }
    }

    protected void clearPrincipals(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.removeAttribute(SAVED_SUBJECT);
        }
    }

    /**
     *
     */
    protected boolean isMandatory(MessageInfo messageInfo) {
        return Boolean.valueOf((String) messageInfo.getMap().get(
                "javax.security.auth.message.MessagePolicy.isMandatory"));
    }

    private LoginContext getLc() throws LoginException {
        if (lc == null) {
            cbh = new MyCBH();

            lc = new LoginContext((lcName != null) ? lcName : getClass().getName(), null, cbh, config);


        }
        return lc;
    }

    /**
     * Saves the original request URL into our session.
     *
     * @param request The request to be saved
     * @param session The session to contain the saved information
     * @throws IOException
     */
    private void saveLoginBackToURL(HttpServletRequest request, HttpSession session) {
        if (session != null) {
            StringBuilder sb = new StringBuilder(request.getRequestURI());
            if (request.getQueryString() != null) {
                sb.append('?');
                sb.append(request.getQueryString());
            }
            session.setAttribute(KEY_EVASION_SAVED_REQUEST_URL, sb.toString());
            LOGGER.log(Level.FINE, "Sauvegarde de la requ\u00eate url={0}", sb.toString());
        }
    }

    /**
     * Return the request URI (with the corresponding query string, if any) from
     * the saved request so that we can redirect to it.
     *
     * @param session Our current session
     */
    private String getSavedRequestURL(HttpSession session) {

        return (String) session.getAttribute(KEY_EVASION_SAVED_REQUEST_URL);

    }

    /**
     *
     */
    @Override
    public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
        return AuthStatus.SUCCESS;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy