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

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

There is a newer version: 2.0.0.2
Show newest version
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.evasion.sam;

import com.evasion.sam.jaas.EvasionGroup;
import com.evasion.sam.jaas.EvasionPrincipal;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.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.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;

/**
 *
 * @author sebastien
 */
public abstract class ServletAuthModule implements ServerAuthModule {

    public static final String AUTH_TYPE_INFO_KEY = "javax.servlet.http.authType";
    public static final String IS_MANDATORY_INFO_KEY = "javax.security.auth.message.MessagePolicy.isMandatory";
    protected static final String POLICY_CONTEXT_OPTIONS_KEY = "javax.security.jacc.PolicyContext";
    protected static final String SAVED_PRINCIPAL_ATTRIBUTE = "javax.security.auth.message.SavedPrincipals";
    protected static final String SAVED_TOKEN_ATTRIBUTE = "com.evasion.SavedToken";
    protected static final String REGISTER_WITH_AUTHENTICATOR = "com.sun.web.RealmAdapter.register";
    protected static final Class[] SUPPORTED_MESSAGE_TYPES = new Class[]{
        javax.servlet.http.HttpServletRequest.class,
        javax.servlet.http.HttpServletResponse.class
    };
    protected static final Logger LOGGER = Logger.getLogger(ServletAuthModule.class.getName());
    protected MessagePolicy requestPolicy;
    protected MessagePolicy responsePolicy;
    protected CallbackHandler handler;
    protected Map options;
    protected String policyContextID;
    private String[] assignedGroups;
    protected boolean isMandatory;
    protected static final String KEY_EVASION_SAVED_REQUEST_URL = "javax.security.evasion.SavedRequestURL";

    @Override
    public void initialize(MessagePolicy requestPolicy,
            MessagePolicy responsePolicy,
            CallbackHandler handler,
            Map options) throws AuthException {

        this.requestPolicy = requestPolicy;
        this.responsePolicy = responsePolicy;

        this.isMandatory = requestPolicy.isMandatory();

        this.handler = handler;
        this.options = options;
        if (options == null) {
            this.options = new HashMap();
        } else {
            this.options = options;
        }
        if (this.options.containsKey(POLICY_CONTEXT_OPTIONS_KEY)) {
            policyContextID = (String) this.options.get(POLICY_CONTEXT_OPTIONS_KEY);
        } else {
            policyContextID = null;
        }
    }

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

    @Override
    public AuthStatus secureResponse(MessageInfo messageInfo,
            Subject serviceSubject) throws AuthException {

        boolean wrapped = false;
        HttpServletRequest r = (HttpServletRequest) messageInfo.getRequestMessage();
        while (r instanceof HttpServletRequestWrapper) {
            r = (HttpServletRequest) ((HttpServletRequestWrapper) r).getRequest();
            wrapped = true;
        }
        if (wrapped) {
            messageInfo.setRequestMessage(r);
        }
        wrapped = false;
        HttpServletResponse s = (HttpServletResponse) messageInfo.getResponseMessage();
        while (s instanceof HttpServletResponseWrapper) {
            s = (HttpServletResponse) ((HttpServletResponseWrapper) s).getResponse();
            wrapped = true;
        }
        if (wrapped) {
            messageInfo.setResponseMessage(s);
        }

        return AuthStatus.SEND_SUCCESS;
    }

    @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();
    }

    protected AuthStatus sendFailureMessage(HttpServletResponse response,
            int status, String message) {
        try {
            response.setStatus(status);
            response.sendError(status, message);
        } catch (IOException ex) {
            // status code has been set, and proper AuthStatus will be returned
            LOGGER.log(Level.WARNING, "jmac.servlet_failed_sending_failure", ex);
        } finally {
            return AuthStatus.SEND_FAILURE;
        }
    }

    protected AuthStatus respondWithRedirect(HttpServletResponse response,
            String url) throws AuthException {
        try {
            // @TODO confirmer l'utilisation du header et du status
            response.addHeader("Pragma", "No-Cache");
            response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
            response.sendRedirect(response.encodeRedirectURL(url));
        } catch (IOException ioe) {
            LOGGER.log(Level.WARNING, "jmac.servlet_redirect_failed", ioe);
            AuthException ae = new AuthException();
            ae.initCause(ioe);
            throw ae;
        }
        return AuthStatus.SEND_CONTINUE;
    }

    protected boolean addGroups(String[] groupNames, Subject clientSubject) {

        if (groupNames != null && groupNames.length > 0) {

            GroupPrincipalCallback gPCB =
                    new GroupPrincipalCallback(clientSubject, groupNames);
            try {
                handler.handle(new Callback[]{gPCB});
                return true;
            } catch (Exception e) {
                // should not happen
                LOGGER.log(Level.WARNING, "jmac.failed_to_assign_groups", e);
            }
        }
        return false;
    }

    protected boolean setCallerPrincipal(EvasionPrincipal userPrincipal, Subject clientSubject) {
        boolean rvalue = true;


        CallerPrincipalCallback callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, userPrincipal);


        try {

            handler.handle(new Callback[]{callerPrincipalCallback});

            LOGGER.log(Level.FINE, "jmac.caller_principal:" + callerPrincipalCallback.getName() + " "
                    + callerPrincipalCallback.getPrincipal());

        } catch (Exception e) {
            // should not happen
            LOGGER.log(Level.WARNING, "jmac.failed_to_set_caller", e);
            rvalue = false;
        }

        return rvalue;
    }

    protected boolean setCallerPrincipal(Subject clientSubject) {
        boolean rvalue = true;
        boolean assignGroups = true;
        List groups = new ArrayList();
        Principal userPrincipal = null;

        for (Principal p : clientSubject.getPrincipals()) {
            String tmp = p.getName();
            LOGGER.fine("Principal utilisé: " + tmp);
            if (p instanceof EvasionGroup && "Roles".equals(tmp)) {

                EvasionGroup evasionGroup = (EvasionGroup) p;

                for (Principal grp : Collections.list(evasionGroup.members())) {
                    groups.add(grp.getName());
                    LOGGER.fine("Groupe associe: " + 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:" + callerPrincipalCallback.getName() + " "
                    + callerPrincipalCallback.getPrincipal());

        } catch (Exception e) {
            // should not happen
            LOGGER.log(Level.WARNING, "jmac.failed_to_set_caller", e);
            rvalue = false;
        }

        return rvalue;
    }

    protected void debugToken(String message, byte[] bytes) {

        if (LOGGER.isLoggable(Level.FINE)) {

            StringBuffer sb = new StringBuffer();
            sb.append("\n");
            sb.append("bytes: ");
            boolean first = true;
            for (byte b : bytes) {
                int i = b;
                if (first) {
                    sb.append(i);
                    first = false;
                } else {
                    sb.append(", ").append(i);
                }
            }

            LOGGER.log(Level.FINE, message, sb);
        }
    }

    protected void debugRequest(HttpServletRequest request) {

        if (LOGGER.isLoggable(Level.FINER) || LOGGER.isLoggable(Level.FINEST)) {
            StringBuffer sb = new StringBuffer();
            sb.append("\n");
            sb.append("Request: " + request.getRequestURL() + "\n");
            sb.append("UserPrincipal: " + request.getUserPrincipal() + "\n");
            sb.append("AuthType: " + request.getAuthType() + "\n");
            sb.append("Headers:" + "\n");
            Enumeration names = request.getHeaderNames();
            while (names.hasMoreElements()) {
                String name = (String) names.nextElement();
                sb.append("\t" + name + "\t" + request.getHeader(name) + "\n");
            }

            LOGGER.log(Level.FINER, "jmac.servlet_request " + sb.toString());

        }
    }

    protected void debugSession(HttpSession session) {
        if (session == null) {
            LOGGER.log(Level.FINER, "Session is null");
        } else {
            if (LOGGER.isLoggable(Level.FINER) || LOGGER.isLoggable(Level.FINEST)) {
                StringBuffer sb = new StringBuffer();
                sb.append("\n");
                sb.append("Session: \n");
                Enumeration attr = session.getAttributeNames();

                String attributName;
                while (attr.hasMoreElements()) {
                    attributName = attr.nextElement();
                    sb.append("\t" + attributName + "\t" + session.getAttribute(attributName) + "\n");
                }
                LOGGER.log(Level.FINER, "Session elements " + 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
     */
    protected String getSavedRequestURL(HttpSession session) {

        return (String) session.getAttribute(KEY_EVASION_SAVED_REQUEST_URL);

    }

    /**
     * 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
     */
    protected 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ête url=" + sb.toString());
        }
    }

    /**
     * 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 savePrincipals(HttpServletRequest request, Subject s) {
        HttpSession session = request.getSession(true);
        session.setAttribute(SAVED_PRINCIPAL_ATTRIBUTE, s.getPrincipals());
    }

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

    /**
     * 
     * @param request
     * @return null si non identifié; enmpty si echec d'authen, sinon le token
     */
    protected String getToken(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Object result = session.getAttribute(SAVED_TOKEN_ATTRIBUTE);
            if (result != null) {
                return (String) result;
            }
        }
        return null;
    }

    protected static void saveTokenId(HttpServletRequest request, String tokenId) {
        HttpSession session = request.getSession(true);
        session.setAttribute(SAVED_TOKEN_ATTRIBUTE, tokenId);
    }

    protected static boolean restorePrincipals(HttpServletRequest request, Subject s) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            Set principals =
                    (Set) session.getAttribute(SAVED_PRINCIPAL_ATTRIBUTE);
            if (principals != null) {
                //session.removeAttribute(SAVED_PRINCIPAL_ATTRIBUTE);
                s.getPrincipals().addAll(principals);
                return true;
            }
        }
        return false;
    }

    protected String getServerName(MessageInfo messageInfo) {
        return ((HttpServletRequest) messageInfo.getRequestMessage()).getServerName();
    }

    protected String getContextPath(MessageInfo messageInfo) {
        return ((HttpServletRequest) messageInfo.getRequestMessage()).getContextPath();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy