A LIVESITE TUTORIALPrepared by Rex StaplesImplementing LiveSite LoginNOTE: THIS TUTORIAL IS FOR LIVESITE 2.2.1 ONLY, LIVESITE 3.0+ USERS SHOULD REFER TO THE 3.x DEVELOPER GUIDECONFIGURE YOUR SITE FOR LOGINFirst, create a page in the site that will serve as your login page. I chose to name mine
Login.
Next, edit the
default.site file in the sites folder of your workarea. Under the
Login Configuration section are four fields related to login configuration: Login Page, Login Object, Login Parameters, and Login Attributes. Login Page and Login Object are mandatory while Login Parameters and Login Attributes are only necessary for Active Directory or LDAP login.
Use the dropdown next to the
Login Page to select the page you just created. Now, any request to access a page where an end user has not already logged in will be sent to the Login page.
For the
Login Object, enter a fully qualified class name of the Java object handling your business logic. The class must implement
com.interwoven.livesite.external.LoginIfc
. This interface has a single method and constants for login success and failure.
Login Parameters are the configuration information for Active Directory or LDAP passed to your server to facilitate authentication. For example, if you use
com.interwoven.livesite.external.impl.LDAPLogin
you will need to pass these configuration parameters:
server="my.ldap.server"
root.dn="dc=my-domain,dc=com"
user.ou="ou=People";
Login Attributes are the user data to automatically set in the user session object after a successful login. For example: name, mail, company, department.
CREATE A LOGIN COMPONENT / ADD IT TO THE LOGIN PAGEThe login component has a form that collects a user name and password and submits that request to a login url. Below is a simple authentication form which may be used in your login component:
<form type="login"><br> <input type="text" name="username"/><br> <input type="password" name="password"/><br> <input type="submit" value="Login"/><br> </form>
The critical factor here is setting the form
type=”login”
so that LiveSite knows to submit this form to the login url. The two input parameters will be made available to your Java login object.
Once created add the login component to the login page so that users redirected to the login page will see the authentication form.
IMPLEMENTING THE LOGIN INTERFACEIn your login Java class implement the method:
public int login(Map params, EndUserSite site, EndUserIfc user)
The
params
map contains the form data submitted with the request; in this instance there is the user name and the password. Both are strings, so fetch them with:
String username = (String) params.get("username");
String password = (String) params.get("password");
The
site
parameter is the site to which the user is logging in. If you are using Active Directory or LDAP, the Login Configuration and Login Attributes may be obtained via the site object through the
getSiteLogin()
getter. For example:
Map config = site.getSiteLogin().getConfig();
String server = (String) config.get(SERVER);
String rootDN = (String) config.get(ROOT_DN);
...
List attribs = site.getSiteLogin().getAttributes();
For more information on the mechanics of an Active Directory or LDAP login, take a peek at the source code for
com.interwoven.livesite.external.impl.LDAPLogin
.
The
user
parameter is a session object unique to each user that is created when they visited the first page in the site. This is the same user object available from all instances of
com.interwoven.livesite.external.ExternalIfc
(and classes extending
com.interwoven.livesite.external.BaseExternal
). For example, you’ve implemented a shopping cart that stores selected items in the user object. The user has been adding items into the cart anonymously, but now needs to login before they proceed to checkout. The user’s items are still in this user object.
If the user’s login is successful, your class must update the user object, and then return
LoginIfc.LOGIN_SUCCESS
.
// login successful
user.setIsLoggedIn(true, site.getName());
return LOGIN_SUCCESS;
If the login failed, then return
LoginIfc.LOGIN_ERROR
.
// login failed
return LOGIN_ERROR;
STORING DATA IN THE USER OBJECTIn addition to saving the logged in state, the user object may be used to store other user-specific information with the
user.setAttribute(String, Object)
method and later retrieved with the
user.getAttribute(String)
method.
If you already have an object tailored to each user, store it as an attribute in the user object and then let your external objects retrieve it as needed. In the example below each shopper has a profile object where shopping cart items are stored along with information about the shopper. This method takes a user object and returns the profile stored therein, or creates, stores, and then returns a new anonymous profile if the user has not yet logged in.
public static Profile getProfile(EndUserIfc user)
{
Profile profile = (Profile) user.getAttribute(USER_ATTRIB_PROFILE);
if (null == profile)
{
profile = new Profile(true); // anonymous profile
user.setAttribute(USER_ATTRIB_PROFILE, profile);
}
return profile;
}
Now this profile can now be used by your external objects to select locale-specific data, deliver personalized content, save shopping cart information, or anything else you can imagine.
POST-LOGIN NAVIGATIONThe default behavior after an unsuccessful login is to return the user to the
Login Page. After a successful login the default behavior forwards the user to the site
Start Page (configured by editing the
default.site file). The most recent versions of LiveSite provide hooks for deterministic navigation.
To control where a user is sent for both successful and unsuccessful logins your login Java object must implement
com.interwoven.livesite.external.AuthNavigationIfc
. This interface has a single method:
public String getNextPage(
EndUserSite site,
EndUserIfc user,
String lastPageVisited)
The
site
and
user
parameters are used to test whether the user is logged in, while the
lastPageVisited
parameter provides the name of the page visited that initiated the login process (either the login page itself, or a “protected” page that sent the user to the login page.) The return value is the name of the page to which the user is navigated.
In the example below, if the user is not successfully logged in, they are sent back to the login page. If the login is successful they are sent to the last visited page; however, if the last visited page is the login page, then they are taken to a page showing an account summary.
ADDENDUM - EXAMPLE XML FILE LOGIN IMPLEMENTATION
public class CustomerLogin implements LoginIfc, AuthNavigationIfc
{
// workarea relative path to login file
public static final String PASSWORD_FILE =
"templatedata/Retail/Customer/users.xml";
// authentication xpath to user
public static final String XPATH_AUTH =
"/users/user[username='%1' and password='%2']";
// username parameter
public static final String PARAM_USERNAME = "username";
// password parameter
public static final String PARAM_PASSWORD = "password";
/**
* Control post-login navigation
*/
public String getNextPage(EndUserSite site,
EndUserIfc user, String lastPageVisited)
{
String target = site.getLoginPage();
if (user.getIsLoggedIn(site.getName()))
{
target = (target.equals(lastPageVisited))
? "Account Summary"
: lastPageVisited;
}
return target;
}
/**
* Handle login.
*/
public int login(Map params, EndUserSite site, EndUserIfc user)
{
String username = (String) params.get(PARAM_USERNAME);
String password = (String) params.get(PARAM_PASSWORD);
if (null == username || null == password)
{
return LOGIN_ERROR;
}
try
{
String filePath = user.getFileDAL().getWebRoot(site)
+ user.getFileDAL().getSeparator()
+ PASSWORD_FILE;
DOMWrapper dom = new DOMWrapper(user.getFileDAL().read(filePath));
String xpath = StringUtil.replaceFirst(StringUtil.replaceFirst(
XPATH_AUTH, "%2", password), "%1", username);
Node userNode = dom.selectSingleNode(xpath);
// test for node, then double check username/password value
if (null == userNode
|| !username.equals(dom.getNodeValue(userNode, PARAM_USERNAME))
|| !password.equals(dom.getNodeValue(userNode, PARAM_PASSWORD)))
{
return LOGIN_ERROR;
}
// populate a customer profile
Profile profile = Profile.getProfile(user);
profile.setAnonymous(false);
profile.setUserName(username);
user.setLocale(new Locale(dom.getNodeValue(userNode, "locale")));
user.setIsLoggedIn(true, site.getName());
return LOGIN_SUCCESS;
}
catch (SAXParseException e)
{
throw new ExternalException("Login Failed", e);
}
}
}