Liferay – Redirect after login


Programando uno de nuestros productos, decidimos incorporar la siguiente funcionalidad: En el caso de que el usuario que accede a la aplicación pertenezca a una única organización (que es la mayoría de los casos), se debería redirigir al usuario, después de hacer login, a la página de la organización.
Mirando la documentación de Liferay, vemos que esto se puede hacer como una post-login action dentro de un hook.
Para ello tendremos que hacer lo siguiente:


Primero, creamos el archivo portal.properties, si no existe ya, dentro de la carpeta src/. Dentro, añadimos la siguiente línea:
...
login.events.post=com.sample.action.PostLoginAction
...


Segundo, añadimos (si no existe ya) la siguiente línea en el archivo liferay-hook.xml:
<hook>
    ...
    <portal-properties>portal.properties</portal-properties>
    ...
</hook>


Tercero, creamos el archivo PostLoginAction.java en la carpeta src/com/sample/action/ con el siguiente contenido:
package com.sample.action;
import java.util.ArrayList;
import java.util.List;
import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.Group;
import com.liferay.portal.model.User;
import com.liferay.portal.service.GroupLocalServiceUtil;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class PostLoginAction extends Action {

    public void run(HttpServletRequest req, HttpServletResponse res) {
        long userId = 0;
        User user = null;
        String redirect = req.getAttribute("javax.servlet.forward.path_info").toString();
        if(Validator.isNull(redirect)){
            redirect = "/c";
        }
        try{
            userId = Long.parseLong(req.getRemoteUser());
            user = UserLocalServiceUtil.getUser(userId);
        }
        catch(Exception e){ e.printStackTrace(); }
        if(redirect.equals("/c") && Validator.isNotNull(user)){
            // Miramos los grupos a los que pertenece el usuario
            List<Group> aux = new ArrayList<Group>();
            List<Group> groups = new ArrayList<Group>();
            try {
                aux = GroupLocalServiceUtil.getUserGroups(user.getUserId());
                for(Group g:aux){
                    if(g.isActive() && g.isOrganization()){
                        groups.add(g);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(groups.size()==1){
                // Si solo hay un grupo, redireccionamos ahí
                redirect = "/group"+groups.get(0).getFriendlyURL();
                redirect = PortalUtil.escapeRedirect(redirect);
                redirect = getCompleteRedirectURL(req, redirect);
                try {
                    res.sendRedirect(redirect);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    protected String getCompleteRedirectURL(
        HttpServletRequest request, String redirect) {
        HttpSession session = request.getSession();

        Boolean httpsInitial = (Boolean)session.getAttribute(
            "HTTPS_INITIAL");
        String portalURL = null;

        if (Boolean.valueOf(PropsUtil.get(PropsKeys.COMPANY_SECURITY_AUTH_REQUIRES_HTTPS)) &&
            !Boolean.valueOf(PropsUtil.get(PropsKeys.SESSION_ENABLE_PHISHING_PROTECTION)) &&
            (httpsInitial != null) && !httpsInitial.booleanValue()) {
            portalURL = PortalUtil.getPortalURL(request, false);
        }
        else {
            portalURL = PortalUtil.getPortalURL(request);
        }
        return portalURL.concat(redirect);
    }
}

Analizando este código vemos que la clase contiene un método run, que es el que se ejecuta después de que Liferay realice la acción de login (y solamente si el login es correcto). Esta funcion toma dos parámetros req y res.


Lo primero que hicimos para saber con qué podíamos trabajar, fue sacar por la consola todos los parámetros y atributos de la variable req. Así, vimos que las variables de login y password no las podíamos coger como parámetros de la petición, ya que no estaban el la variable req. Mirando los métodos accesibles desde req, encontramos getRemoteUser y vemos, sacando este valor por la consola, que contiene  en formato String el id del usuario que se acaba de loguear.


El segundo escollo a superar es cómo saber si la petición original tenía redirect o no. Como el redirect no lo podemos leer como parámetro porque no está en la variable req, miramos los atributos de la petición y vemos que el atributo “javax.servlet.forward.path_info” contiene el valor “/c” si no hay redirect, y el valor del redirect en el caso de que éste exista. Esto es importante porque si hay redirect, queremos que nos lleve ahí después de loguearnos, y si no hay redirect, nos tiene que llevar a la raiz del site de la organización.


Así, en el caso de que “javax.servlet.forward.path_info” sea igual que “/c” y el usuario no sea null, miramos los grupos a los que pertenece el usuario, que estén activos y sean organizaciones, y si solamente hay uno, llevamos al usuario a su página raiz.


Leave a Reply

Your email address will not be published. Required fields are marked *