LogoffServlet.java

package sk.iway.iwcm;

import sk.iway.iwcm.stripes.AfterLogonLogoffInterceptor;
import sk.iway.iwcm.system.stripes.CSRF;
import sk.iway.iwcm.users.UserDetails;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Map;

@WebServlet(name = "LogOff",
        urlPatterns = {"/logoff.do","/admin/logoff.do"}
)
public class LogoffServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Logger.debug(LogoffServlet.class,"LogoffServlet  CALLED - GET");
        execute(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Logger.debug(LogoffServlet.class,"LogoffServlet  CALLED - POST");
        execute(request,response);
    }

    public void execute(HttpServletRequest request,
                                 HttpServletResponse response)
            throws IOException, ServletException
    {

        HttpSession session = request.getSession();
        Identity user = (Identity) session.getAttribute(Constants.USER_KEY);
        if (user != null && user.isAdmin())
        {
            sk.iway.iwcm.stat.StatDB.addAdmin(request);
        }

        boolean csrfTokenIsValid = true;
        if (Constants.getBoolean("logoffRequireCsrfToken"))
        {
            String token = request.getParameter(CSRF.getParameterName());
            if (Tools.isEmpty(token)) token = request.getHeader("x-csrf-token");

            if (Tools.isEmpty(token) || CSRF.verifyTokenAndDeleteIt(session, token)==false || request.getMethod().equalsIgnoreCase("POST")==false)
            {
                Logger.error(getClass(), "CSRF token mismatch, logoff failed");
                csrfTokenIsValid = false;
            }
        }

        this.callLogonLogoffInterceptor(user, request);

        /**
         * install-custom actions before logoff
         * method takes one argument -  request
         * return value is not dealt with
         * format is fully.qualified.class.name.methodName
         */
        String beforeLogoffAction = Constants.getString("beforeLogoffAction");
        if(Tools.isNotEmpty(beforeLogoffAction))
        {
            try{
                int i = beforeLogoffAction.lastIndexOf('.');
                String beforeLogoffClass = beforeLogoffAction.substring(0, i);
                String beforeLogoffMethod = beforeLogoffAction.substring(i+1);
                Logger.debug(getClass(), "Before logoff action:" + beforeLogoffAction);
                Class<?> c = Class.forName(beforeLogoffClass);
                Method m;
                Class<?>[] parameterTypes = new Class<?>[] {HttpServletRequest.class};
                Object[] arguments = new Object[] {request};
                m = c.getDeclaredMethod(beforeLogoffMethod, parameterTypes);
                m.setAccessible(true); //NOSONAR
                m.invoke(null, arguments);
            }
            catch(Exception e){
                //sk.iway.iwcm.Logger.error(e);
                Logger.debug(getClass(), "Failed to perform before logoff action:" + beforeLogoffAction + " cause: " +e.getMessage());
            }
        }

        if (csrfTokenIsValid) {
            session.removeAttribute(Constants.USER_KEY);
            session.removeAttribute("loggeduser");
            session.invalidate();
            String admin = "";
            if (user != null && user.isAdmin()) admin = " (ADMIN)";
            if (user != null) Adminlog.add(Adminlog.TYPE_USER_LOGOFF, "LogoffAction - user"+admin+" successfully logged off: name = " + user.getLogin(), -1, -1);

            removePermanentLogon(request, response);

            //zmaz z cache user objekty
            if (user != null)
            {
                Cache cache = Cache.getInstance();
                cache.removeUserAllUserObjects(user);
            }
        }

        // Forward control to the specified success URI
        if (request.getParameter("forwardDocId")!=null)
        {
            response.sendRedirect("/showdoc.do?docid="+ Tools.getIntValue(request.getParameter("forwardDocId"), 4));
            return;
        }
        else if (request.getParameter("forward")!=null)
        {
            String forward = Tools.replace(Tools.sanitizeHttpHeaderParam(request.getParameter("forward")), "//", "/");
            //security: allow only forwards to local addresses, if requested to external address use forwardDocId with redirect set in webpage
            if (forward.startsWith("/") && forward.contains("//")==false) {
                response.sendRedirect(forward);
                return;
            }
        }
        //request.getRequestDispatcher("success").forward(request,response);
        //response.sendRedirect("/");
        String logoffRedirect = Constants.getString("logoffRedirectUrl");
        response.sendRedirect(logoffRedirect);
    }

    private void callLogonLogoffInterceptor(UserDetails user, HttpServletRequest request)
    {
        String interceptorClassName = Constants.getString("stripesLogonLogoffInterceptorClass");

        if (Tools.isEmpty(interceptorClassName)) {
            interceptorClassName = Tools.getStringValue((String) request.getAttribute("afterSaveInterceptor"), "");
        }

        if (Tools.isNotEmpty(interceptorClassName)) {
            try
            {
                @SuppressWarnings("unchecked")
                Class<? extends AfterLogonLogoffInterceptor> interceptorClass = (Class<? extends AfterLogonLogoffInterceptor>) Class.forName(interceptorClassName);
                AfterLogonLogoffInterceptor interceptor = interceptorClass.getDeclaredConstructor().newInstance();

                interceptor.logoff(user, request);
            }
            catch (Exception e)
            {
                sk.iway.iwcm.Logger.error(e);
            }
        }
    }

    /**
     * @param request
     * @throws UnsupportedEncodingException
     * @author mhalas
     */
    private void removePermanentLogon(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException
    {
        try
        {
            String cookieName = "wjpltrack";

            Cookie[] cookies = request.getCookies();
            Cookie plcookie = null;
            if(cookies != null && cookies.length > 0)
            {
                for(Cookie c : cookies)
                {
                    if(c.getName().equals(cookieName)){
                        plcookie = c; break;
                    }
                }
                if(plcookie != null)
                {
                    String[] keyua = plcookie.getValue().split("-");
                    @SuppressWarnings("unchecked")
                    Map<String, String> plmap = (Map<String, String>)Constants.getServletContext().getAttribute(cookieName);
                    if (plmap != null) plmap.remove(keyua[0]);

                    //delete cookie from client
                    Cookie cookie = new Cookie(cookieName, URLEncoder.encode("deleted","UTF-8"));
                    cookie.setMaxAge(0);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }
            }
        }
        catch (Exception e)
        {
            sk.iway.iwcm.Logger.error(e);
        }

    }

}