The following code is a modified version of the 3.1 login.jsp file. It has been modified to add a prompt for the user’s email address. Figure 2-4 illustrates the login page that these changes produce.
Figure 2-4 Custom Credentials
Such a JSP file must be used with a contract that uses a method that defines the query for the new attribute. The method also needs to define which login file has been modified to display the prompt. For more information about this process, see Customizing the Default Login Page to Prompt for Different Credentials.
The sample code contains the following the text for the prompt:
<td align=left> <label>Email Address:</label> </td>
It also adds an input element for the query variable:
<td align=left> <input type="text" class="smalltext" name="Ecom_User_Mail" size="30"> </td>
These elements are both part of the new <tr> element that has been added to the file. These lines are marked in bold in the following sample file.
<%@ page language="java" %>
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="com.novell.nidp.*" %>
<%@ page import="com.novell.nidp.servlets.*" %>
<%@ page import="com.novell.nidp.resource.*" %>
<%@ page import="com.novell.nidp.resource.jsp.*" %>
<%@ page import="com.novell.nidp.ui.*" %>
<%
ContentHandler handler = new ContentHandler(request,response);
String target = (String) request.getAttribute("target");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//<%=handler.getLanguageCode()%>">
<html lang="<%=handler.getLanguageCode()%>">
<head>
<META HTTP-EQUIV="Content-Language" CONTENT="<%=handler.getLanguageCode()%>">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<style type="text/css" media="screen">
td label { font-size: 0.85em ; padding-right: 0.2em; }
label { font-size: 0.77em; padding-right: 0.2em; }
input { font-family: sans-serif; }
.instructions { color: #4d6d8b; font-size: 0.8em; margin: 0 10px 10px 0 }
</style>
<script type="text/javascript" src="<%= handler.getImage("showhide_2.js",false)%>"></script>
<script language="JavaScript">
var i = 0;
function imageSubmit()
{
if (i == 0)
{
i = 1;
document.IDPLogin.submit();
}
return false;
}
</script>
</head>
<body style="background-color: <%=handler.getBGColor()%>" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" rightmargin="0" onLoad="document.IDPLogin.Ecom_User_ID.focus();" >
<form name="IDPLogin" enctype="application/x-www-form-urlencoded" method="POST" action="<%= (String) request.getAttribute("url") %>" AUTOCOMPLETE="off">
<input type="hidden" name="option" value="credential">
<% if (target != null) { %>
<input type="hidden" name="target" value="<%=target%>">
<% } %>
<table border=0 style="margin-top: 1em" width="100%" cellspacing="0" cellpadding="0">
<tr>
<td style="padding: 0px">
<table border=0>
<tr>
<td align=left>
<label><%=handler.getResource(JSPResDesc.USERNAME)%></label>
</td>
<td align=left>
<input type="text" class="smalltext" name="Ecom_User_ID" size="30">
</td>
</tr>
<tr>
<td align=left>
<label>Email Address:</label>
</td>
<td align=left>
<input type="text" class="smalltext" name="Ecom_User_Mail" size="30">
</td>
</tr>
<tr>
<td align=left>
<label><%=handler.getResource(JSPResDesc.PASSWORD)%></label>
</td>
<td align=left>
<input type="password" class="smalltext" name="Ecom_Password" size="30">
</td>
</tr>
<tr>
<td align=right colspan=2 style="white-space: nowrap">
<input alt="<%=handler.getResource(JSPResDesc.LOGIN)%>" border="0" name="loginButton2" src="<%= handler.getImage("btnlogin.gif",true)%>" type="image" value="Login" onClick="return imageSubmit()">
</td>
</tr>
</table>
</td>
</tr>
<%
String err = (String) request.getAttribute(NIDPConstants.ATTR_LOGIN_ERROR);
if (err != null)
{
%>
<td style="padding: 10px">
<div class="instructions"><%=err%></div>
</td>
</tr>
<% } %>
<%
if (NIDPCripple.isCripple())
{
%>
<tr>
<td width="100%" align="center"><%=NIDPCripple.getCrippleAdvertisement(request.getLocale())%></td>
</tr>
<%
}
%>
</table>
</form>
</body>
</html>
To create a custom nidp.jsp file that uses custom credentials, you need to modify the nidp.jsp file, create a method and contract for the file, and modify the main.jsp file. For instructions, see Customizing the nidp.jsp File and Adding Logic to the main.jsp File.
Figure 2-5 illustrates the login page that the following custom nidp.jsp file and main.jsp file create.
Figure 2-5 Custom Branding with Custom Credential Prompts
The credential frame uses the same modifications in the sample from Section 2.4.1, Modified login.jsp File for Credential Prompts. The following sections provide the other required sample files to create this login page and information on the required method and contract:
The background, menu, and border colors are set to black. These colors are specified in the following lines in the sample file:
// Background color String bgcolor = "#000000"; // Menu color String menucolor = "#000000"; // Border color String bcolor = "#000000";
Figure 2-6 illustrates the image (images2.jpeg) that this custom page uses for the header background image:
Figure 2-6 Background Image
This image is the repeatable image that allows the header to be resized. This image is specified in the following lines in the file:
// The header background image that gets repeated String hdrBgndImg = "/custom_images/images2.jpeg";
Figure 2-7 illustrates the image (images3.jpeg) that this custom page uses for the product logo that appears on left of the header frame.
Figure 2-7 Header Image
Figure 2-8 illustrates the image (hhbimages.jpeg) that this custom page uses to replace the Novell company logo on the right of the header frame.
Figure 2-8 Company Logo
The following lines define what appears as the title for the browser window:
<title>HHB WORLD</title>
The following line defines the header title value:
String hdrTitle = "Enter MY WORLD";
Its position is controlled by the following line in the file:
#title { position: absolute; font-size: 1.2em; color: white; top: 18px; left: 85px; }
The top position has been modified from 13px to 18px and the left position has been modified from 55px to 85px. The other lines in this section control the position of the other items in the header.
The lines that have been modified are marked in bold in the following file.
<% ContentHandler handler = new ContentHandler(request,response); // Background color String bgcolor = "#000000"; // Menu color String menucolor = "#000000"; // Border color String bcolor = "#000000"; // The header background image that gets repeated String hdrBgndImg = "/custom_images/images2.jpeg"; String hdrImage = "/custom_images/images3.jpeg"; String hdrLogo = "/custom_images/hhbimages.jpeg"; String hdrTitle = "Enter MY WORLD"; String query = request.getQueryString(); if (query != null && query.length() > 0) query = "&" + query; else query = ""; %> <!DOCTYPE HTML PUBLIC "-//W3C//Dtd HTML 4.0 transitional//<%=handler.getLanguageCode()%>"> <html lang="<%=handler.getLanguageCode()%>"> <head> <title>HHB WORLD</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link href="<%= handler.getImage("hf_menu.css",false)%>" rel="stylesheet"> <link href="<%= handler.getImage("HF_message.css",false)%>" rel="stylesheet"> <link href="<%= handler.getImage("HF_obj_list_table.css",false)%>" rel="stylesheet"> <style> * { margin: 0; padding: 0; } #header { background-image: url(<%= handler.getImage(hdrBgndImg,false)%>); background-repeat: repeat-x; } #logo { position: absolute; top: 0px; right: 0px; } #title { position: absolute; font-size: 1.2em; color: white; top: 18px; left: 85px; } #subtitle { position: relative; font-size: .9em; color: black; white-space: nowrap; top: 0px; left: 0px; text-align: right; } #mcontent { position: relative; padding: 5px; background-color: <%=bgcolor%>; } #content { width: 100%; border: 0; margin: 0; padding: 0; overflow: none; height: 376px; background-color: <%=bgcolor%>;} #logoutbut { position: absolute; top: 25px; right: 35px; } #helpbutlogin { position: absolute; color: yellow; top: 25px; right: 10px; } #loggingbut { position: absolute; color: blue; top: 25px; right: 65px; } .NLtab .tab1s { background-color: <%=menucolor%>; padding-left: 3px; padding-right: 8px; text-align: center; white-space: nowrap; } .NLtab .tab1s a { text-decoration: none; } .NLtab span.tab1s { padding:5; color: white; font-size: 0.9em; font-weight: bold; line-height: 17px; background-color: transparent; background-image: none; text-decoration: none; } .NLtab .tab1u { background-color: <%=bgcolor%>; padding-left: 3px; padding-right: 3px; text-align: center; white-space: nowrap; border-left: 1px solid <%=bcolor%>; border-right: 1px solid <%=bcolor%>; border-top: 1px solid <%=bcolor%>; } .NLtab span.tab1u { border: none; padding:5; color: black; font-size: 0.8em; font-weight: bold; line-height: 17px; text-decoration: none; background-color: transparent; } .NLtab tr.subtab td { color: white; padding: 2px } .NLtab tr.subtab a { font-size: .8em; color: white; text-decoration: none; padding: 2px 5px 2px 5px} .selx { border: 1px solid rgb(239, 238, 236); font-size: 1em; font-weight: bolder; background-repeat: repeat-x; background-position: 0pt bottom;} .unselx { border: 0px; font-size: .9em; font-weight: normal; background-image: none; } </style> <script> var g_curCard = null; // initial displayed card var g_cardContainer = null; // div that holds all the authentication cards var g_curSubtab = null; // subtab currently displayed var g_curTab = null; // tab currently displayed var menuItem = 0; function showHide(i) { document.getElementById('menu1').style.display='none'; document.getElementById('menu2').style.display='none'; document.getElementById('submenu1').style.display='none'; document.getElementById('submenu2').style.display='none'; document.getElementById('menu' + i).style.display='block'; document.getElementById('submenu' + i).style.display='block'; if (i == 1) switchContentPage("<%= handler.getJSP("content")%>"); else switchContentPage("<%= handler.getJSP("IdentityEditor")%>"); } function switchContentPage(newSrc) { parent.document.getElementById("content").src = newSrc; } function onloadhandler() { g_cardContainer = document.getElementById("cardcontainer"); g_curSubtab = document.getElementById("loginsubtab"); g_curTab = document.getElementById("authtab"); g_curCard = document.getElementById("selectedCard0"); } function showhideTab(divid) { var element1 = document.getElementById(divid); if(element1.style.display == "none") { element1.style.display = "block"; g_curTab.style.display = "none"; g_curTab = element1; } } function subtabchange(divid) { var element1 = document.getElementById(divid); var element2 = g_curSubtab; element1.className = "selx"; if (element1.id != element2.id) { element2.className = "unselx"; } g_curSubtab = element1; } function showHelp() { var helpURL = "login.html"; if (g_curSubtab.id == "fedsubtab") helpURL = "<%=handler.getHelp("federations.html")%>"; else if (g_curSubtab.id == "myprofile") helpURL = "<%=handler.getHelp("myprofile.html")%>"; else if (g_curSubtab.id == "sharing") helpURL = "<%=handler.getHelp("sharing.html")%>"; else if (g_curSubtab.id == "loginsubtab") helpURL = "<%=handler.getHelp("userlogin.html")%>"; else if (g_curSubtab.id == "newcardsubtab") helpURL = "<%=handler.getHelp("newcard.html")%>"; else if (g_curSubtab.id == "logTicketsubtab") helpURL = "<%=handler.getHelp("logticket.html")%>"; var w; w = window.open(helpURL, "nidsPopupHelp", "toolbar=no,location=no,directories=no,menubar=no,scrollbars=yes,resizable=yes,width=500,height=500"); if (w != null) { w.focus(); } } </script> </head> <body onload="onloadhandler()"> <table width=100% border=0 cellpadding=0 cellspacing=0 bgcolor=<%=bgcolor%> > <tr> <td> <table cellspacing=0 width=100% border=0> <tr> <td width=100%> <div id="header"><img src="<%=handler.getImage(hdrImage,false)%>"></div> <div id="logo"><img src="<%=handler.getImage(hdrLogo,false)%>"></div> <div id="title"><%=hdrTitle%></div> </td> </tr> </table> </td> </tr> <tr> <td> <table cellspacing=5 width=100%> <tr> <td> <%@ include file="menus.jsp" %> </td> </tr> </table> </td> </tr> <tr> <td> <table cellspacing=0 border=0 width=100%> <tr> <td> <iframe scrolling=no id="content" src="<%=handler.addCardParm(handler.getJSP(handler.isJSPMsg() ? handler.getJSPMessage().getJSP() : NIDPConstants.JSP_CONTENT)) + query%>" frameborder=0></iframe> </td> </tr> </table> </td> </tr> </table> </body> </html>
The following sample file has two types of modifications. The following line has been added so that the URI of the contract can be read and used as a condition for selecting the login page to display:
String strContractURI = hand.getContractURI();
The following lines define the login page to use when the URI of the contract is set to login/custom.
else if(strContractURI != null && strContractURI.equals("login/custom")) { %> <%@ include file="custom.jsp" %> <% }
The lines that have been added are marked in bold in the following file.
<%@ page language="java" %> <%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%> <%@ page import="com.novell.nidp.*" %> <%@ page import="com.novell.nidp.resource.jsp.*" %> <%@ page import="com.novell.nidp.ui.*" %> <%@ page import="com.novell.nidp.common.util.*" %> <%@ page import="com.novell.nidp.liberty.wsf.idsis.apservice.schema.*" %> <% ContentHandler hand = new ContentHandler(request,response); String strContractURI = hand.getContractURI(); // Is there a JSP defined on a class definition or a method definition // that should be displayed as the main jsp here? if (hand.contractDefinesMainJSP()) { %> <%@ include file="mainRedirect.jsp" %> <% } else if(strContractURI != null && strContractURI.equals("login/custom")) { %> <%@ include file="custom.jsp" %> <% } // This is the jsp used by default else { %> <%@ include file="nidp.jsp" %> <% } %>
After modifying the two files, you still need to create a method and a contract. The method needs to use a name/password class and have the following properties defined:
Query property values:
Property Name: Query
Property Value: (&(objectclass=person)(mail=%Ecom_User_Mail%))
JSP property values:
Property Name: JSP
Property Value: <filename>
Replace <filename> with the name of your login page that modifies the credential prompts. Do not include the JSP extension in the value.
You then need to create a contract that uses this method and assign it to a protected resource.
To create this type of page, you need to start with the login.jsp file that ships with Access Manager 3.1 and then add the required code for a header. Figure 2-9 illustrates such a page.
Figure 2-9 Custom Page Derived from the 3.1 login.jsp File
To create this page, see the following sections:
This custom page does not modify the credential frame. The lines that define the window title (HHB CUSTOM LOGIN), the page header title (IT’S A NEW WORLD), and the image (hhbimages.png) are marked in bold in the following sample file.
<%@ page language="java" %> <%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%> <%@ page import="java.util.*" %> <%@ page import="com.novell.nidp.*" %> <%@ page import="com.novell.nidp.servlets.*" %> <%@ page import="com.novell.nidp.resource.*" %> <%@ page import="com.novell.nidp.resource.jsp.*" %> <%@ page import="com.novell.nidp.ui.*" %> <% ContentHandler handler = new ContentHandler(request,response); String target = (String)request.getAttribute("target"); String hdrImage = "/custom_images/hhbimages.jpeg"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//<%=handler.getLanguageCode()%>"> <html lang="<%=handler.getLanguageCode()%>"> <head> <title>HHB CUSTOM LOGIN </title> <META HTTP-EQUIV="Content-Language" CONTENT="<%=handler.getLanguageCode()%>"> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <style type="text/css" media="screen"> td label { font-size: 0.85em ; padding-right: 0.2em; } label { font-size: 0.77em; padding-right: 0.2em; } input { font-family: sans-serif; } .instructions { color: #4d6d8b; font-size: 0.8em; margin: 0 10px 10px 0 } </style> <script type="text/javascript" src="<%= handler.getImage("showhide_2.js",false)%>"></script> <script language="JavaScript"> var i = 0; function imageSubmit() { if (i == 0) { i = 1; document.IDPLogin.submit(); } return false; } </script> </head> <body text="lightcyan" style="background-color:Black" marginwidth="300" marginheight="100" leftmargin="350" topmargin="0" rightmargin="0" onLoad="document.IDPLogin.Ecom_User_ID.focus();" > <br> <h1><u> IT’S A NEW WORLD</u></h1> <form name="IDPLogin" enctype="application/x-www-form-urlencoded" method="POST" action="<%= (String) request.getAttribute("url") %>" AUTOCOMPLETE="off"> <input type="hidden" name="option" value="credential"> <% if (target != null) { %> <input type="hidden" name="target" value="<%=target%>"> <% } %> <table border=0 style="margin-top: 1em" width="20" cellspacing="0" cellpadding="0"> <tr> <div id="headimage"><img src="<%=handler.getImage(hdrImage,false)%>" alt="" height="80" width="150" border="0"></div> </tr> <tr> <td style="padding: 0px"> <table border=0> <br><br> <tr> <td align=center> <label><%=handler.getResource(JSPResDesc.USERNAME)%></label> </td> <td align=center> <input type="text" class="smalltext" name="Ecom_User_ID" size="30"> </td> </tr> <tr> <td align=center> <label><%=handler.getResource(JSPResDesc.PASSWORD)%></label> </td> <td align=center> <input type="password" class="smalltext" name="Ecom_Password" size="30"> </td> </tr> <tr> <td align=right colspan=2 style="white-space: nowrap"> <input alt="<%=handler.getResource(JSPResDesc.LOGIN)%>" border="0" name="loginButton2" src="<%= handler.getImage("btnlogin.gif",true)%>" type="image" value="Login" onClick="return imageSubmit()"> </td> </tr> </table> </td> </tr> <% String err = (String) request.getAttribute(NIDPConstants.ATTR_LOGIN_ERROR); if (err != null) { %> <td style="padding: 10px"> <div class="instructions"><%=err%></div> </td> </tr> <% } %> <% if (NIDPCripple.isCripple()) { %> <tr> <td width="100%" align="center"><%=NIDPCripple.getCrippleAdvertisement(request.getLocale())%></td> </tr> <% } %> </table> </form> </body> </html>
After modifying the file, you still need to create a method and a contract. The method needs to use a name/password class and have the following properties defined:
JSP property values:
Property Name: JSP
Property Value: <filename>
Replace <filename> with the name of your custom login page. Do not include the JSP extension in the value.
MainJSP property values:
Property Name: MainJSP
Property Value: true
You then need to create a contract that uses this method and assign it to a protected resource.
To create this type of page, you need to start with the login.jsp file that shipped with Access Manager 3.0. This file needs to be modified to run on Access Manager 3.1.x. For instructions, see Modifications Required for a 3.0 Login Page
in the Novell Access Manager 3.1 SP2 Installation Guide.
Figure 2-10 illustrates a page that has been modified to remove the Novell branding and logo. It has also been modified to prompt the user for an e-mail address in addition to a username and password.
Figure 2-10 Custom Page Derived from the 3.0 login.jsp File
To create this page, see the following sections:
The bold lines in the following sample file are the lines that have been modified to change the branding and the login prompts.
<%@ page language="java" %> <%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%> <%@ page import="com.novell.nidp.common.provider.*" %> <%@ page import="java.util.*" %> <%@ page import="com.novell.nidp.ui.*" %> <%@ page import="com.novell.nidp.*" %> <%@ page import="com.novell.nidp.servlets.*" %> <%@ page import="com.novell.nidp.resource.*" %> <%@ page import="com.novell.nidp.resource.jsp.*" %> <%@ page import="com.novell.nidp.common.xml.w3c.*" %> <% ContentHandler handler = new ContentHandler(request,response); %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//<%=handler.getLanguageCode()%>"> <html lang="<%=handler.getLanguageCode()%>"> <head> <link rel="stylesheet" href="<%= request.getContextPath() %>/images/hf_style.css" type="text/css"> <style type="text/css" media="screen"><!-- #headimage { position: relative; top: 0px; left: 0px; z-index: 1} #title { position: relative; top: 40px; left: 5px; color: white; z-index: 4} #locallabel { position: relative; top: 78px; left: 10px; z-index: 4} #login { text-align: center } --></style> <META HTTP-EQUIV="Content-Language" CONTENT="<%=handler.getLanguageCode()%>"> <title>MY WORLD</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <script type="text/javascript" src="<%= request.getContextPath() %>/images/showhide_2.js"></script> <script language="JavaScript"> var i = 0; function imageSubmit() { if (i == 0) { i = 1; document.IDPLogin.submit(); } return false; } </script> </head> <body marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" rightmargin="0" onLoad="document.IDPLogin.Ecom_User_ID.focus();" > <form name="IDPLogin" enctype="application/x-www-form-urlencoded" method="POST" action="<%= (String) request.getAttribute("url") %>" AUTOCOMPLETE="off"> <table style="margin-top: 6em" width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="50%" height="80 px"> </td> <td colspan="2"> <div id="title"><b>HHB Partner</b></div> <div id="locallabel"><b>My Company</b></div> <div id="headimage"><img src="<%= request.getContextPath() %>/images/Odyssey_Head.gif" alt="" height="80" width="550" border="0"></div> </td> <td width="100%"> </td> </tr> <tr> <td width="50%"> </td> <td style="background-color: #efeee9; padding: 10px" colspan="2"> <% String err = (String) request.getAttribute(NIDPConstants.ATTR_LOGIN_ERROR); if (err != null) { %> <div><label><%=err%></label></div> <% } // Determine if this login page is being used for account identification // purposes %> <span id="login2" style="display: block;"> <table> <tr> <td nowrap="nowrap"> <div> <label style="width: 100px"><%=handler.getResource(JSPResDesc.USERNAME)%></label></label> </div> </td> <td width="100%" nowrap="nowrap"> <div> <input type="text" class="smalltext" name="Ecom_User_ID" size="30"> </div> </td> </tr> <tr> <td nowrap="nowrap"> <div> <label style="width: 100px">Email Address:</label></label> </div> </td> <td width="100%" nowrap="nowrap"> <div> <input type="text" class="smalltext" name="Ecom_User_Mail" size="30"> </div> </td> </tr> <tr> <td nowrap="nowrap"> <div> <label><%=handler.getResource(JSPResDesc.PASSWORD)%></label> </div> </td> <td style="white-space: nowrap"> <div> <input type="password" class="smalltext" name="Ecom_Password" size="30"> <input alt="<%=handler.getResource(JSPResDesc.LOGIN)%>" border="0" name="loginButton2" src="<%=handler.getImage("btnlogin.gif",true)%>" type="image" value="Login" onClick="return imageSubmit()"> </div> </td> </tr> </table> </span> </td> <td width="100%"> </td> </tr> <tr> <td width="50%"></td> <td style="background-color: #E6D88C; padding-left: 10px"><img style="padding-right: 200px" src="<%= request.getContextPath() %>/images/LAP_interoperable_logo_100.gif" align="absmiddle" border="0"></td> <td style="background-color: #E6D88C; padding-right: 10px" align="right" width="100"> </td> <td width="100%"></td> </tr> <% if (NIDPCripple.isCripple()) { %> <tr> <td colspan=4 width="100%" align="center"><%=NIDPCripple.getCrippleAdvertisement(request.getLocale())%></td> </tr> <% } %> </table> </form> </body> </html>
After modifying the file, you still need to create a method and a contract. The method needs to use a name/password class and have the following properties defined:
Query property values:
Property Name: Query
Property Value: (&(objectclass=person)(mail=%Ecom_User_Mail%))
JSP property values:
Property Name: JSP
Property Value: <filename>
Replace <filename> with the name of your custom login page. Do not include the JSP extension in the value.
MainJSP property values:
Property Name: MainJSP
Property Value: true
You then need to create a contract that uses this method and assign it to a protected resource.