« Back to Configuring

Custom Post-login Redirect

This article needs updating. For more information, please see Wiki - Need Updating

There are articles with content about the same topic. See Customizing the default page after login

Introduction #

The default behavior after login is to redirect the user to his private community (if the user has one). A common requested customization is to change this behavior so that the logged in user will be redirected to a different page (to the guest community, the last page they were at, or some other page based on some custom logic).

Steps#

This can be done by editing 2 files:

  ext/ext-ejb/classes/portal-ext.properties:

set

  auth.forward.by.last.path=true

This will overwrite the "auth.forward.by.last.path" value in portal.properties which is set to "false" by default. Now, after users login, they will be redirected to the last page they were at, instead of their own private community.

::In v4.3, auth.forward.by.last.path is true by default.

However, if we wanted to customize this redirect even further, we just need to edit one more file.

v4.2#

  com.liferay.portal.events.LoginPostAction.java 

(the bottom of the .run() method has the following code that has been commented out):

  // To manually set a path for the user to forward to, edit
  // portal.properties and set auth.forward.by.last.path to true.
  
  /*Map params = new HashMap();
  
  params.put("p_l_id", new String[] {"PRI.3.1"});
  
  LastPath lastPath = new LastPath("/c", "/portal/layout", params);
  
  ses.setAttribute(WebKeys.LAST_PATH, lastPath);*/

If you switch the "auth.forward.by.last.path" variable to "true", then after you login, it will redirect you to the url you were just at before you logged out, which is stored in the variable "lastPath".

v4.3#

  com.liferay.portal.events.DefaultLandingPageAction.java

(see comments in the file as well)

  if (Validator.isNotNull(path)) {
    LastPath lastPath = new LastPath(
      StringPool.BLANK, path, new HashMap());
  
    HttpSession ses = req.getSession();
  
    ses.setAttribute(WebKeys.LAST_PATH, lastPath);
  }
  
  // The commented code shows how you can programmaticaly set the user's
  // landing page. You can modify this class to utilize a custom alogrithm
  // for forwarding a user to his landing page. See the references to this
  // class in portal.properties.
  
  /*Map params = new HashMap();
  
  params.put("p_l_id", new String[] {"PRI.1.1"});
  
  LastPath lastPath = new LastPath("/c", "/portal/layout", params);
  
  ses.setAttribute(WebKeys.LAST_PATH, lastPath);*/

All#

But here is where the "lastPath" variable is determined. So lets say that you wanted to redirect certain users to a certain page, if you changed that "lastPath" value.. you now control what page the newly logged in user would get redirected to.

Helpful notes in writing custom redirect#

You could get the logged in user info via: PortalUtil.getUserId(req)

v4.2#

By default, the guest community is: PUB.1.1

so to redirect to the public community change the "params.put" line to look like:

  params.put("p_l_id", new String[] {"PUB.1.1"});

v4.3#

In v4.3 p_l_id's are long integers, not Strings.

Also, a user's first layout can't be assumed as in 'v4.2'. But we have a convenient method for finding the default Layout's p_l_id:

  user.getGroup().getDefaultPrivatePlid()

Best Practices - Extending the Source#

If you just wanted to do this quickly, you can just uncomment the code at the bottom in your LoginPostAction.java file and add your own logic to set the lastPath variable at the end of the run() method, but we would be mixing our changes in with the original source files. This makes our changes hard to keep track of and messy when it comes to updating to newer versions of Liferay. The best way to make these modifications would be to "extend the source".

For this example, we will be creating a new class called "CustomLoginPostAction", this will ONLY contain our additional logic. We will hook in this class so that our logic gets executed after the standard LoginPostAction class gets called. To do this, follow these steps:

Create folder structure#

We will be creating a folder structure that mirrors the folder structure of the portal source code (LoginPostAction.java is in "portal/portal-ejb/src/com/liferay/portal/events/"). By default, the "liferay/portal/events" portion of the folder structure doesnt exist in the EXT environment. In our EXT environment, create the path "ext/ext-ejb/src/com/liferay/portal/events/".

Create a custom LoginPostAction class#

Create a new file in our "ext/ext-ejb/src/com/liferay/portal/events/" folder called "CustomLoginPostAction.java". We will be placing our custom code in the run() method, which will be executed after the run() method of the standard LoginPostAction class.

package com.liferay.portal.events;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.liferay.portal.struts.Action;
import com.liferay.portal.struts.ActionException;
import com.liferay.portal.struts.LastPath;
import com.liferay.portal.util.WebKeys;

/**
 * @author  Scott Lee*
 */
public class CustomLoginPostAction extends Action {

	public void run(HttpServletRequest req, HttpServletResponse res)
		throws ActionException {

		try {
			HttpSession ses = req.getSession();
			
			// To manually set a path for the user to forward to, edit
			// portal.properties and set auth.forward.by.last.path to true.

			Map params = new HashMap();

			//params.put("p_l_id", new String[] {"PRI.3.1"});
			params.put("p_l_id", new String[] {"PUB.1.1"});

			LastPath lastPath = new LastPath("/c", "/portal/layout", params);

			ses.setAttribute(WebKeys.LAST_PATH, lastPath);
		}
		catch (Exception e) {
			throw new ActionException(e);
		}
	}

}

Overwrite values in portal.properties#

We will overwrite a couple values in "portal.properties" by editing our "portal-ext.properties" file. Add these 2 lines of code:

  auth.forward.by.last.path=true
  login.events.post=com.liferay.portal.events.LoginPostAction,com.liferay.portal.events.CustomLoginPostAction

Deploy Changes#

Make sure tomcat is shutdown, and then run the "ant deploy" from EXT

0 Attachments
91873 Views
Average (6 Votes)
The average rating is 4.166666666666667 stars out of 5.
Comments
Threaded Replies Author Date
Excellent ! Thanks ! petar banicevic July 15, 2008 2:38 PM
Great source of information. Could you explain... Justen L Britain August 21, 2008 8:49 AM
I am using liferay 4.4.2 tomcat 5.5 .Can any... John Charls September 25, 2008 6:46 AM
Great Content. Is this still valid (the first... Daniel Kreiseder July 13, 2009 6:28 AM
will this work for 5.2.3? Ziggy © August 10, 2009 1:46 PM
I am using liferay 5.2.3 tomcat 5.5 .Can any... suresh koppula May 29, 2010 11:48 PM
I want to be redirect use organization... ahmet kilic October 26, 2009 11:18 AM
I am using Liferay 6.04. I am trying to... Khanh Vo October 1, 2010 3:26 PM
Can someone please comment on how to get... Phil H Orion November 2, 2010 4:59 PM
ext project should put in Root folder? lv yulin November 16, 2010 11:32 PM
mark leon li August 16, 2012 6:54 PM
Hi i have a one problem in liferay with the... Mehdi Khan November 14, 2012 3:48 AM

Excellent ! Thanks !
Posted on 7/15/08 2:38 PM.
Great source of information. Could you explain in more detail though such things like this line of code:
params.put("p_l_id", new String[] {"PRI.3.1"});
What is the difference between "PRI.3.1" and "PUB.1.1"?
Posted on 8/21/08 8:49 AM.
I am using liferay 4.4.2 tomcat 5.5 .Can any body tell about redirecting a page from login page to a specific user(not based on organization ).Thanks in advance.
Posted on 9/25/08 6:46 AM in reply to Justen L Britain.
Great Content.

Is this still valid (the first choice) for Liferay 5.2.3 ?
Posted on 7/13/09 6:28 AM.
will this work for 5.2.3?
Posted on 8/10/09 1:46 PM in reply to Daniel Kreiseder.
I want to be redirect use organization properties but which class using don't know
Posted on 10/26/09 11:18 AM.
I am using liferay 5.2.3 tomcat 5.5 .Can any body tell about redirecting a page from login page to a specific user( based on community ).ie., once i login i need to look at the pages in the community i was joined.Thanks in advance.
Posted on 5/29/10 11:48 PM in reply to Daniel Kreiseder.
I am using Liferay 6.04. I am trying to Extending the source but am trying to figure out where the source code should be. The instruction above mention the EXT directory. Is this the EXT directory in the liferay-plugins-sdk-6.0.4?

Thanks
Posted on 10/1/10 3:26 PM.
Can someone please comment on how to get Liferay 6.0.5, Liferay IDE 1.1.0, Plugins-sdk-6.0.x to forward users to their private pages after Login...

1) in Hook Project -->
2) in portal.properties ::
auth.forward.by.last.path=true /
login.events.post=com.liferay.portal.events.LoginPostAction,com.test.GotoPrivat­eLandingPageAction
does not work. The event is never fires and the code is never invoked.
Posted on 11/2/10 4:59 PM in reply to Khanh Vo.
ext project should put in Root folder?
Posted on 11/16/10 11:32 PM in reply to Phil H Orion.
Posted on 8/16/12 6:54 PM.
Hi i have a one problem in liferay with the loading of Message Carosuel,its loading slowlely or sometimes when i click on the refresh page the Message Carosul taking long time to load and its happening on Internet Explorer.Please help me in this .
Below is the velocity code thats written in template.
#set ($rolesService = $portal.getClass().forName("com.liferay.portal.service.RoleLocalServiceUtil").ge­tMethod("getService", null).invoke(null, null))#set ($roleList = $rolesService.getUserRelatedRoles($getterUtil.getLong( $request.get("remote-user")),$getterUtil.getLong($groupId)))#set ($userService = $serviceLocator.findService("com.liferay.portal.service.UserLocalService"))#set ($user =$userService.getUserById($getterUtil.getLong($request.get("remote-user"))))#set­($selectedRole = "false")#foreach($roles in $roleList) #if($roles.getName().equalsIgnoreCase( 'active') || $roles.getName().equalsIgnoreCase( 'retiree') || $roles.getName().equalsIgnoreCase( 'deferred')) #set($userRole =$roles.getName().trim()) #end#end #foreach($message in $CarouselName.getSiblin­gs()) #foreach($item in $message.CarouselRo­le.options) #if($­item.equalsIg­noreCase($userRole)) #set($selectedRole = "true") #set($boarderRole = $userRole) #end #end #end #foreach($type in $layout.options) #set($layoutType = $type)#end#if( $boarderRole.equalsIgnoreCase($userRole­)) #if($layoutType == "Right") <div class="yui3-skin-sam" style="width:100% !important; ><div id="gmc1"> <div class="span-8" > <div id="containerSmall" class="yui3-carousel-loading"> #end #if($layoutType == "Left")<div class="yui3-skin-sam" style="width:100% !important; backgroundemoticonFFF; border: 1px solid #C2D4A5; position: relative;"><div id="gmc"> <div class="span-16"> <div id="container" class="yui3-carousel-loading"> #end <ol> #foreach($message in $CarouselName.getSiblin­gs()) #foreach($item in $message.CarouselRo­le.op­tions) #­if(­$item­.equalsIgnoreCase($userRole)) #set($selectedRole = "true") <li><div class="yui3-li-content"> #if($message.image.getData()!="") <img src="$message.image.getData()" alt="$message.alt.getData()"/> #end <div class="copy"> <h2>$message.title.getData()</h­2> <p>$message.contents.getData()<br><a href="$message.linkUrl.getData()">$message.link.getData()</a></p> ­ </div> </div> </li> ­#end #end #end </ol> <div class="yui3-nav">&nbsp;</div> </div> </div> </div> </div> #end<script type="text/javascript">var intervalArray=new Array();var isPause = 0;var pauseitm,flag,focusitm,changestate,pausebtn;focusitm=false;changestate=false; YUI({ //Last Gallery Build of this module gallery: 'gallery-2011.05.18-19-11' }).use("gallery-carousel", "gallery-carousel-anim", "substitute", function (Y) {#if($layoutType == "Left") /* Set Li Width Start */ var AllLis = Y.all("#gmc .span-16 #container li"); var LiParentWidth = (Y.one('body').get('offsetWidth') * 90) / 100; if (LiParentWidth < 1000){LiParentWidth = 1000}; var LiParentWidth = (LiParentWidth * 70) / 100; var LiParentWidth = ((LiParentWidth - 20) * 97 ) / 100; var ParentWidths = (LiParentWidth + (50*100)) * Y.all("#gmc .span-16 #container li").size(); AllLis.each(function (node) { node.setStyle('width', parseInt(LiParentWidth)); }); Y.one("#gmc .span-16 #container").setStyle('width', parseInt(LiParentWidth)); Y.one("#gmc .span-16 ol").setStyle('width', parseInt(ParentWidths)); /* Set Li Width End */#endvar carousel = new Y.Carousel({ #if($layoutType == "Left") boundingBox: "#container", contentBox: "#container > ol", #end #if($layoutType == "Right") boundingBox: "#containerSmall", contentBox: "#containerSmall > ol", #end numVisible :1, isCircular:tr­ue, increment:5, autoPlayInterval: $timer.getData() // replace in startAutoPlay as well }); Y.Carousel.prototype.startAutoPlay = function() { var B = this; B.set("autoPlayInterval",$timer.getData()); // replace the var value in contentready function as well. u = B.get("autoPlayInterval"); pauseitm = setInterval (doScrollForward, u); intervalArray.push(pauseitm); function doScrollForward() { B.scrollForward();­ //currentCount = B.get("selectedItem"); } } Y.Carousel.prototype.stopAutoPlay = function() { for(var i = 0;i<intervalArray.length;i++){ if(intervalArray == pauseitm) { intervalArray.splice(i,1); } } pauseitm = clearInterval (pauseitm); } Y.on("contentready", function () { carousel.plug(Y.CarouselAnimPlugin, { animation: { speed: 0.2, effect: Y.Easing.easeOut } }); // Hide the page navigation when only 1 announcement is present if(carousel.get("numItems")==1) { carousel.set("hidePagination",­true); } carousel.render(); //carousel.startAutoPlay(­); // If current item is not zero, forward it as it displays first announcement everytime after ajax refresh //if(currentCount!=-1) { // carousel.set("selectedItem",p­arseInt(currentCount)); //carousel.scrollForward(­); //} // If ajax refresh has happened when mouse was over the announcement then dont start the auto play if(isPause == 0) { carousel.startAutoPlay(); } /*Code to change the button state after Ajax call begins @57258*/ if(isPause == 1) { var bb = carousel.get("boundingBox"); pausebtn = bb.all('.yui3-carousel-button'); pausebtn._nodes[2].className = "yui3-carousel-button yui3-carousel-play-button"; } /*Code to change the button state after Ajax call ends @57258*/ // Hide the navigation buttons when less than or equal to 5 announcements are present if(carousel.get("numItems")!=1 && carousel.get("numItems")<=5) { document.getElementById("navigationFirstButton").style.display = 'none'; document.getElementById("navigationNextButton").style.display = 'none'; } /* Code to capture the href of anchor and open the URL 57258 */ Y.on('click', function (e) { var targetURL = e.target.getAttribute("href"); window.open(tar­getURL); }, ".yui3-li-content .copy a"); }, #if($layoutType == "Left")"#container"#end #if($layoutType == "Right")"#containerSmall"#end ); }); </script>
Posted on 11/14/12 3:48 AM.