Skip Headers
Oracle® WebCenter Framework Building a WebCenter Application Step by Step
10g (10.1.3.2.0)

Part Number B31073-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

6 Creating a Login Page

In this chapter you will create the new login page that users are redirected to for authentication. WebCenter applications typically have a notion of public pages and allow for explicit as well as implicit authentication. This means that users can log into the application by clicking the login link before they navigate to secured content (explicit), or they can navigate to a secured page, which will redirect them to the login page for the application (implicit). See "Securing your WebCenter Application" in the Oracle WebCenter Framework Developer's Guide for more information about implicit and explicit authentication. Figure 6-1 shows a sample login page you are going to build in this chapter.

Figure 6-1 Login Page From the SRDemo Application

Description of Figure 6-1 follows
Description of "Figure 6-1 Login Page From the SRDemo Application"

The SRDemoSample_Starter application already contains a login page, SRLogin.jspx, which is located as shown in Figure 6-2.

Figure 6-2 Original SRDemo Login Page

Description of Figure 6-2 follows
Description of "Figure 6-2 Original SRDemo Login Page"

Since the login page uses a login form, you do not typically use an ADF Faces page for a login page, because the ADF Faces lifecycle will remap the login form's submit action and its form fields to internal references, which would break the login functionality. However, the login page is an important part of the application. It can contain customizable information such as portlets and data controls and it can also benefit from skinning features that are available to ADF Faces pages. Alternatively, you may also want to implement a login portlet. In this chapter you will learn how you can build an ADF Faces-based login page for the SRDemo application. This login page's form also uses the J2EE security container login method, j_security_check. This chapter includes the following sections:

Step 1: Creating a Login Page

To create the ADF Faces-based login page, perform the following steps:

  1. In the Applications Navigator, under the UserInterface project, expand the Web Content folder if necessary.

  2. Right-click the infrastructure folder (shown in Figure 6-2) and select New.

  3. In the New Gallery dialog box, expand the Web Tier node.

  4. Select JSF.

  5. In the Items list, select JSF JSP.

  6. Click OK to display the Create JSF JSP dialog box.

  7. If you are on the Welcome page of the wizard, click Next to display the JSP File page.

  8. In the File Name field, enter SRLoginADF.jspx.

  9. Select JSP Document (*.jspx).

  10. Click Next to display the Component Binding page.

  11. Select Automatically Expose UI Components in a New Managed Bean.

  12. Click Next to display the Tag Libraries page and select ALL Libraries.

  13. Make sure that the following libraries are listed in Selected Libraries:

    • JSF Core

    • JSF HTML

    • ADF Faces Components

    • ADF Faces HTML

    • ADF Portlet Components

    • Customizable Components Core

  14. Click Finish to create the page.

  15. Save the page.

  16. In the Source View of the SRLoginADF.jspx page, copy the code shown in Example 6-1 and paste just before the f:view tag.

    Example 6-1 Reference to the SRDemo Resource Bundle

    <!-- Resource Bundle for Translatable Strings within Application =========== -->
    <f:loadBundle basename="oracle.srdemo.view.resources.UIResources" var="res"/>
    
  17. Save the file.

  18. Switch to Design View.

  19. From the Component Palette, select ADF Faces Core.

  20. Select a PanelPage component and drag it on to the body element in the Structure pane. When prompted, do not add a form, because we will add our own form later and delete the default form element.

  21. Change the Title property, by binding it to a string from the resource bundle that ships with the application. In the Property Inspector, click Title.

  22. Click the Bind to Data icon (the database icon at the top of the Property Inspector). This displays the Bind to Data dialog box.

  23. Under JSP objects, select res and find the srlogin.pageTitle variable.

  24. Move it to the Expression field and click OK.

  25. Add some facets in the page title key, srlogin.pageTitle. To do so, find the existing branding facet code shown in Example 6-2.

    Example 6-2 The Original Branding Facet

    <f:facet name="branding"/>
    
  26. Replace the branding image facet code with the facet code shown in Example 6-3. This will set the logo image within the branding facet to reflect the appropriate company branding logo for the chosen skin.

    Example 6-3 The New Branding Facet

    <!-- Site Branding Section (Top Left of Page) ============================== -->
          <f:facet name="branding">
                <af:objectImage source="/skins/#{skinBean.currentSkin}/skin_images/SRBranding.gif"/>
          </f:facet>
    
  27. Next, add the copyright facet to the new login page. In the SRLoginADF.jspx page, find the existing copyright facet code shown in Example 6-4.

    Example 6-4 The original Copyright facet

    <f:facet name="appCopyright"/>
    
  28. Replace this copyright facet with the facet shown in Example 6-5. This will load the branding image from the skin bean, which ensures that it can be changed at run time, when the skin is changed.

    Example 6-5 The Copyright Facet

    <!-- Copyright Message -->
         <f:facet name="appCopyright">
           <h:panelGroup>
             <af:outputText value="#{res['srdemo.copyright']}"/>
             <af:objectSpacer width="10" height="10"/>
           </h:panelGroup>
         </f:facet>
    
  29. Now that you have created the login page as an ADF Faces page, you cannot just add the login form using form elements from the Component Palette. This would cause the form elements to be serialized and remapped at runtime by the ADF Faces lifecycle. Instead, we will design the page such that the login component is independent from the form surrounding the active JSF components (Those that submit back to the Faces lifecycle). While this could be achieved by using verbatim tags inside the JSF page, it greatly increases the complexity and limits the flexibility available. To allow the login component to be treated as a single element (rather than a series of escaped HTML tags), which can be moved around the page and easily skinned, you can separate the HTML form from the User Interface and inject it dynamically at runtime. This can be achieved by including it in the backing bean and exposing the returned HTML in an OutputText object that is rendered in the User Interface. To do this, perform the following steps:

    Note:

    The code is available in the SRLoginADF_Backing_Code.txt file located in the starter ZIP file (in the root directory).
    1. Open the Backing Bean, SRLoginADF.java, located in the backing/infrastructure folder, as shown in Figure 6-3, to add the HTML injection code to the Backing Bean so that it can be pulled into the page at runtime. The basis for this code is to generate the appropriate HTML directly in the page. As such, the various getter methods return the appropriately marked up HTML as a simple string. The advantage of using this dynamically generated HTML is the ability to include references to the skin information. The integration of the HTML into the Faces page is simplified by removing the need for verbatim tags and CDATA escapes within the page.

      Figure 6-3 Location of SRLoginADF.java in the Applications Navigator

      Description of Figure 6-3 follows
      Description of "Figure 6-3 Location of SRLoginADF.java in the Applications Navigator"

    2. Now add the Java code to the file. To do so, add the import statements shown in Example 6-6.

      Example 6-6 Import Statement

      import javax.faces.application.FacesMessage;
      import javax.faces.context.FacesContext;
      import javax.servlet.http.HttpSession;
      import oracle.adf.share.ADFContext;
      import oracle.adf.view.faces.component.core.output.CoreMessages;
      import oracle.srdemo.view.util.JSFUtils;
      
    3. Add Backing Bean properties to top of SRLoginADF.java, as shown in Example 6-7. These getter methods for these properties will later be referenced in Expression Language in the login page.

      Example 6-7 Backing Bean Properties

      private String  _loginStyleBlock   = null;
      private String  _loginScriptBlock  = null;
      private String  _loginFormBlock    = null;
      private boolean _validLoginAttempt = true;
      

      Table 6-1 describes these properties.

      Table 6-1 Backing Bean Properties in the SRLoginADF.java File

      Variable Description

      loginStyleBlock

      Contains the HTML for defining a CSS class

      loginScriptBlock

      Contains the HTML for the required JavaScript used by the login form

      loginFormBlock

      Contains the HTML for the login form itself

      validLoginAttempt

      A boolean value that indicates whether the current user is able to perform another login attempt or not. This is set to false if the user exceeds the number of valid login attempts.


    4. Insert the getloginStyleBlock getter method in the Backing Bean. See Example 6-8.

      This generates a simple stylesheet that defines flashing text that is used by the login form to indicate that the authentication process is taking place. The HTML that is generated by this method is invisible, and as such, the output string can be rendered outside of the body of the page.

      Example 6-8 getloginStyleBlock Getter Methods

      /**
        * ============================================================================
        * Function to generate the CSS style class referenced in Login Form
        * ============================================================================
        * @return
        */
      public String getloginStyleBlock()
      {
        _loginStyleBlock = "\n\n"
                         + "<!-- 
      ========= CSS Style Block Generated in Backing Bean ========= -->\n"
                         + "<style type=\"text/css\">\n"
                         + ".VP_Blink {text-decoration: blink;}\n"
                         + "</style>\n"
                         + "<!--
       ============================================================= -->"
                         + "\n\n";
        return (_loginStyleBlock);
      }
      
    5. Insert the getloginScriptBlock getter method the Backing Bean. See Example 6-9.

      This method generates the <script> block that contains the JavaScript functions that are used by the login form. These include field validation and form-submission actions. As the JavaScript is dynamically generated, it is possible to include the references to the current skin as well as appropriate strings from the resource bundle. For example, if the current skin is set to myCompany, then the following line sets the JavaScript alert message to be the value that is defined in the resource bundle key: SRLoginADF.myCompany.jsAlert.

      String alertMsg    = JSFUtils.getStringFromBundle("SRLoginADF." +
      currentSkin + ".jsAlert");
      

      In a similar way, the method determines the correct icon to indicate that the authentication is in progress and generates the URL to that icon based on the Faces external context.

      Example 6-9 getloginScriptBlock Getter Methods

      /**
       * ============================================================================
       * Method getloginScriptBlock() to generate a JScript Submit form block.
       * This function implements the current skin and generates simple JavaScript
       * to validation the user input prior to the Authentication submit action.
       * ============================================================================
       * @return
       */
      public String getloginScriptBlock()
      {
       String currentSkin = (String)
       JSFUtils.getManagedBeanValue("skinBean.currentSkin");
       String alertMsg    = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                         + currentSkin + 
                                                         ".jsAlert");
       String valPwdMsg   = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                         + currentSkin + 
                                                         ".AuthMsg");
       String urlBaseRef  =
      FacesContext.getCurrentInstance().getCurrentInstance().getExternalContext().getRequestContextPath();
       String processIcon = urlBaseRef + "/skins/" + currentSkin + "/skin_images/process_animation.gif";
            _loginScriptBlock = "\n\n"
                         + "<!-- 
      ======== JavaScript Block Generated in Backing Bean ========= -->\n"
                         + "<SCRIPT language=\"JavaScript\" type=\"text/JavaScript\">\n"
                         + "(new Image(32,32)).src=\"" + processIcon +"\";\n"
                         + "function SubmitForm(AuthFrm){\n"
                         + "var alertMsg =\""   + alertMsg  + "\";\n"
                         + "var valPwdMsg = \"" + valPwdMsg + "\";\n\n"
                         + "if (((AuthFrm.j_username.value == null) || (AuthFrm.j_username.value ==\"\")) ||\n"
                         + "    ((AuthFrm.j_password.value == null) || (AuthFrm.j_password.value ==\"\")))\n"
                         + " {\n  alert(alertMsg);\n  return false;\n }\n else\n {\n"
                         + " var divTag = document.getElementById(\"vp\");\n"
                         + " divTag.innerHTML = '<table width=\"50\" border=\"0\"><tr>' +\n"
                         + "                    '<td align=\"center\"><img src=\"" 
                                                 + processIcon + "\" width=\"32\"
                                                 height=\"32\"></td>' +\n"
                         + "                    '<td align=\"left\"><font size=\"-2\"
                                                 class=\"VP_Blink\">' + valPwdMsg +
                                                 '</font></td>' +\n"
                         + "                    '</tr></table>';\n"
                         + " return true;\n"
                         + " }\n}\n"
                         + "</SCRIPT>\n"
                         + "<!--
       ============================================================= -->"
                         + "\n\n";
      return (_loginScriptBlock);
      }
      
    6. Insert the getLoginFormBlock getter method in the Backing Bean. See Example 6-10.

      This method generates a string that defines the HTML login form that is rendered inside the page. As the HTML is dynamic it is able to include references to the current skin as well as keys in the resource bundle. Furthermore, as the login page is designed to be customized after login, the HTML is sensitive to the authenticated state of the user in that the HTML disabled property is dynamically set using the ADF security context's isAuthenticated(); method.

      In this case, if the login page is accessed once the user is authenticated, then the login page (while rendered) is deactivated to prevent subsequent login attempts. For example, this is the case when the page is accessed from the site administration page, as discussed in Chapter 9, "Building a Site Administration Page".

      In the following example, you can see that the string variable htmlDisable is either "disabled="true"", or null, based on the ADF Security context's isAuthenticated state:

      String htmlDisable =(ADFContext.getCurrent().getSecurityContext().isAuthenticated() ? "disabled=\"true\"" : null);
      

      The following code snippet shows you how the htmlDisable string is subsequently used to activate or disable the form elements, such as input fields and Submit button:

      <input type=\"text\" name=\"j_username\" "+ htmlDisable + "/></td>\n"
      

      Example 6-10 getLoginFormBlock Getter Method

      /**
       * ===========================================================================
       * Method getLoginFormBlock() generates the standard Credential Form used
       * by container security. The function implements the current skin values and
       * returns the required HTML which is subsequently output using an OutputText
       * object populated using EL. While this could also have been achieved by 
       * directly using the Verbatim tags within the JSPX itself, this would require the
       * use of CDATA escapes and complicates the design of the page (the login form
       * is exposed through a faces component in this case.)
       *
       * Note as the Login Page contains customizable components, the HTML form elements
       * generated are disabled if the user is currently authenticated.
       * ==========================================================================
       * @return
       */
      
      public String getLoginFormBlock()
      {
        String currentSkin       = (String)
      JSFUtils.getManagedBeanValue("skinBean.currentSkin");
        String userNameLabel     = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                                + currentSkin +
                                                                ".userName");
        String passwordLabel     = JSFUtils.getStringFromBundle("SRLoginADF." 
                                                                + currentSkin +
                                                                ".password");
        String submitButtonLabel = JSFUtils.getStringFromBundle("SRLoginADF." +
                                                                 currentSkin +
                                                                ".buttonLabel");
        String htmlDisable       =
      (ADFContext.getCurrent().getSecurityContext().isAuthenticated() ? "disabled=\"true\"" : null);
             _loginFormBlock = "\n\n"
                        + "<!-- 
      ======== Login Form Block Generated in Backing Bean ========= -->\n"
                        + "<form name=\"LoginForm\" id=\"LoginForm\" \n"
                        + " action=\"j_security_check\" method=\"POST\"
                            onSubmit=\"return SubmitForm(this)\" >\n"
                        + "<table cellspacing=\"5\" cellpadding=\"0\" border=\"0\"
                           width=\"50%\" bgcolor=\"#FFFFFF\" width=\"240\" >\n"
                        + " <tr>\n"
                        + "  <td nowrap>" + userNameLabel + "</td>\n"
                        + "  <td nowrap><input type=\"text\" name=\"j_username\" 
                          "  + htmlDisable + "/></td>\n"
                        + " </tr>\n"
                        + " <tr>\n"
                        + "  <td nowrap>" + passwordLabel + "</td>\n"
                        + "  <td nowrap><input type=\"password\" name=\"j_password\" 
                          " + htmlDisable + "/></td>\n"
                        + " </tr>\n"
                        + " <tr>\n"
                        + "  <td nowrap height=\"34\"><DIV id=\"vp\"></DIV></td>\n"
                        + "  <td nowrap>\n"
                        + "    <input type=\"submit\" value=\"" + submitButtonLabel + 
                          "\" " + htmlDisable + "/></td>\n"
                        + "  </td>\n"
                        + " </tr>\n"
                        + "</table>\n"
                        + "</form>\n"
                        + "<!--
       ============================================================= -->"
                        + "\n\n" ;
        return ( _loginFormBlock);
      }
      
    7. Save the file.

  30. From the Component Palette, select ADF Faces Core.

  31. Select PanelHorizontal and drag it on to the page component.

  32. Set the Valign property to middle in the Property Inspector.

  33. Select ObjectImage from the ADF Faces Core Component Palette and drag it onto the PanelHorizontal component. Set the source attribute to the following value:

    /skins/#{skinBean.currentSkin}/skin_images/LoginSplash.gif
    
  34. Select ObjectSpacer and drag it on to the page just below the ObjectImage component.

  35. From the Component Palette, select Customizable Components Core.

  36. Select PanelCustomizable and drag it below the ObjectSpacer element you just added in the Structure pane. When prompted, do not add a form, because we will add our own form later and delete the default form element.

  37. Set the Layout property for the PanelCustomizable component to vertical.

  38. From the Component Palette, select ADF Faces Core.

  39. Now add the following to the PanelCustomizable component:

    • an objectSpacer

    • an objectSeparator

    • an objectSpacer

    • a panelHorizontal

      set the Halign property to center

    • an objectSpacer

    • an objectSeparator

    • an objectSpacer

  40. Select PanelBox and drag it onto the PanelHorizontal component.

  41. Set the Text property of the PanelBox to be the login component header by referencing the resource bundle, using expression language (EL). To do this, click the Bind to Data icon. This displays the Bind to Data dialog box.

  42. Under JSP objects, select res and find the SRLoginADF.credentialHeader variable.

  43. Select OutputText from the ADF Faces Core Component Palette and drag it onto the PanelBox component.

  44. In the Property Inspector, bind the Value property of the OutputText component to data from a managed bean by selecting JSF Managed Beans, backing_infrastructure_SRLoginADF, and then loginFormBlock as shown in Figure 6-4.

  45. Set the OutputText component's Escape property to false.

  46. Drag another OutputText component above the body tag in the Structure pane, just below the top of the page, as shown in Figure 6-5.

    Figure 6-5 Structure Pane

    Description of Figure 6-5 follows
    Description of "Figure 6-5 Structure Pane"

  47. Bind the Value property to data from the backing bean by selecting JSF Managed Beans, backing_infrastructure_SRLoginADF, and loginStyleBlock and set the Escape property to false.

  48. Drag another OutputText component onto the Structure pane, just above the body tag.

  49. Bind the Value property to data from the backing bean by selecting JSF Managed Beans, backing_infrastructure_SRLoginADF, and loginScriptBlock, and then set the Escape property to false.

  50. In the SRLoginADF.jspx page, open the panelPage node in the Structure pane, then drag the Messages component onto the messages facet.

  51. Save the file.

Step 2: Creating a Login Error Page

To create a login error page, perform the following steps:

  1. In the Applications Navigator, under the UserInterface project, expand the Web Content node, if necessary.

  2. Right-click the infrastructure folder (shown in Figure 6-2) and select New.

  3. In the New Gallery dialog box, expand the Web Tier node.

  4. Select JSP.

  5. In the Items list, select JSP.

  6. Click OK to display the Create JSP dialog box.

  7. If you are on the Welcome page of the wizard, click Next to display the Create JSP page.

  8. In the File Name field, enter SRLoginErrorPage.jsp.

  9. On the Error Page Options page of the wizard, select Do Not Use an Error Page to Handle Uncaught Exceptions in This File.

  10. On the Tag Libraries page, select All Libraries, and then select JSTL Core 1.1 and move it to the Selected Libraries list.

  11. Click Finish.

  12. Add the JSTL code shown in Example 6-11 just before the <html> element to track the login attempts.

    Example 6-11 JSTL Code to Track the Number of Login Attempts

    <!-- ===========================================================================
     For the SRDemo Demo we will track the number of Login Attempts against the file 
     based repository (In a deployed system this would be handled by the IdM system).
     This counter is then used in the backing bean to define if the login attempt
     is valid (referenced in EL as "loginAttemptValid").
     =========================================================================== -->
    <c:set var="LoginErrorCount" 
           scope="session" 
           value="${sessionScope.LoginErrorCount == null ? 1 :sessionScope.LoginErrorCount + 1}"/>
    <c:redirect url="/faces/infrastructure/SRLoginADF.jspx"/>
    

    This JSTL code stores in a simple session variable the number of times the error page is called (due to invalid login) and redirects the user back to the original login page where the actual processing takes place.

  13. Save the SRLoginErrorPage.jsp file.

  14. Open the backing bean, SRLoginADF.java and add the getMessages1() method shown in Example 6-12.

    The following two methods use the Faces external context to return the session variable that was set by the JSTL in the error page, to determine the number of times the user has attempted to log in.

    The following code snippet shows you how to return the session variable based on the Faces context and the associated HTTP session. The returned object is converted to a local integer to evaluate whether the user's login attempt is valid or not. For example, a three-attempt limit can thus be enforced.

    FacesContext facesContext = FacesContext.getCurrentInstance();
    HttpSession  session = (HttpSession)facesContext.getExternalContext().getSession(true);
    Object loginAttempts  = session.getAttribute("LoginErrorCount");
    Integer loginAttemptCount = (loginAttempts == null)? 0 : Integer.parseInt(loginAttempts.toString());
    

    Note:

    The getMessages1 method is the default getter method created for the message component of the PanelPage. If your message component is not messages1, you must change the name of the method.Having determined the current number of logging attempts, the getMessages1 method sets the appropriate error string (returned from the resource bundle) for the Faces message component. In this case greater than one attempt indicates an invalid username and password combination and greater than three attempts indicate that the user has exceeded the legal limit.

    Example 6-12 getMessage1() Method

    /**
         * ===========================================================================
         * Function getMessages1() determines the current number of login failures and
         * sets the appropriate error message in the Faces Context
         * ===========================================================================
         * @return
         */
        public CoreMessages getMessages1()
        {
         if (!ADFContext.getCurrent().getSecurityContext().isAuthenticated())
         {
           String       currentSkin       = (String)
           JSFUtils.getManagedBeanValue("skinBean.currentSkin");
           FacesContext facesContext      = FacesContext.getCurrentInstance();
           HttpSession  session           = (HttpSession)
           facesContext.getExternalContext().getSession(true);
           Object       loginAttempts     = session.getAttribute("LoginErrorCount");
           Integer      loginAttemptCount = (loginAttempts == null)? 0 :
           Integer.parseInt(loginAttempts.toString());
           String       loginErrorMessage = null;
           if (loginAttemptCount >0)
           {
            if (loginAttemptCount >2) {
             loginErrorMessage = JSFUtils.getStringFromBundle(
                                 "SRLoginADF." + currentSkin +
                                 ".tooManyLoginAttempts");
            }
            else {
             loginErrorMessage = JSFUtils.getStringFromBundle(
                        "SRLoginADF." + currentSkin + ".invalidLogin");
            }
            FacesMessage fm =  new FacesMessage(
                       FacesMessage.SEVERITY_INFO,loginErrorMessage,null);
            facesContext.addMessage(null, fm );
           }
         }
         return messages1;
        }
    
  15. Open the backing bean, SRLoginADF.java and add the isValidLoginAttempt method shown in Example 6-13.

    The boolean value returned by the isValidLoginAttempt method is referenced in the rendered property of the output text component which holds the login form HTML code. In this case, when the number of valid attempts is greater than three, the login form is not rendered on the page and the user is prevented from logging in again.

    Example 6-13 isValidLoginAttempt Method

    /**
         * ===========================================================================
         * Method isValidLoginAttempt() evaluates the number of invalid login attempts
         * performed by the user and returns false if greater than 3. (used in EL to
         * show/hide the Login Page components.
         * ===========================================================================
         * @return
         */
        public boolean isValidLoginAttempt()
        {
          _validLoginAttempt = true;
          if (!ADFContext.getCurrent().getSecurityContext().isAuthenticated()) {
             FacesContext facesContext      = FacesContext.getCurrentInstance();
             HttpSession  session           = (HttpSession)
             facesContext.getExternalContext().getSession(true);
             Object       loginAttempts     = session.getAttribute("LoginErrorCount");
             Integer      loginAttemptCount = (loginAttempts == null)? 0 
            : Integer.parseInt(loginAttempts.toString());
                 
             if (loginAttemptCount >2){ _validLoginAttempt = false; }
          }
          return (_validLoginAttempt);
        }
    
  16. Save the file.

  17. Open SRLoginADF.jspx.

  18. Drag an ObjectImage into the PanelBox below the OutputText object, and set the source property to the following value:

    source="/skins/#{skinBean.currentSkin}/skin_images/BadLoginAttempt.gif"
    
  19. Bind the rendered property to the negated (opposite) value of the isValidLoginAttempt() method in the backing bean. Set the rendered property to the following value:

    #{!backing_infrastructure_SRLoginADF.validLoginAttempt}
    

    By doing this, the image will be rendered only if the login attempt is invalid.

  20. Set the rendered property of the OutputText object to the value of the isValidLoginAttempt() method as follows:

    #{backing_infrastructure_SRLoginADF.validLoginAttempt}
    

    This ensures the login form is rendered only when it is valid for a user to try to login.

Step 3: Adding a Rich Text Portlet to the Login Page

In this section, you will add a Rich Text portlet to the login page. To do this, perform the following steps:

  1. Make sure your Rich Text portlet has been registered before proceeding. Refer to "Step 1: Adding a Rich Text Component" in Chapter 5, "Creating a Public Welcome Page" for the details.

  2. From the Component Palette, choose RichTextPortletProducer, then select Rich Text from the list. In the Structure pane, drag the Rich Text Portlet above the top-most objectSpacer within the panelCustomizable.

  3. Select the Rich Text portlet and open the Property Inspector.

  4. Set the following properties:

    Properties Value
    AllModesSharedScreen true
    IsMinimizable false
    IsMaximizable false
    DisplayHeader false

  5. From the Component Palette, choose RichTextPortletProducer, then select Rich Text from the list. In the Structure pane, drag the Rich Text Portlet below the last objectSpacer within the panelCustomizable.

  6. Select the Rich Text portlet and open the Property Inspector.

  7. Set the following properties:

    Properties Value
    AllModesSharedScreen true
    IsMinimizable false
    IsMaximizable false
    DisplayHeader false

  8. Save the page.

You can now customize this Rich Text Portlet by going back to the login page after you have logged in. Chapter 9, "Building a Site Administration Page" describes how you can do this.

Step 4: Editing Authorization for the Login Page

Next, we need to define the appropriate privileges for the login page. All users should be able to view the page and managers should also be able to edit the page, so that they can update the Rich Text portlet, for example. To set the security on the login page, perform the following steps:

  1. In the Applications Navigator, right-click SRLoginADF.jspx.

  2. Select Go to Page Definition.

  3. Click Yes, if you are prompted to create a new page definition. The page definition file opens in the Structure pane.

  4. Right-click the Page Definition file and select Edit Authorization. This displays the Authorization Editor.

  5. Grant View privilege to anyone and Edit privilege to manager, as shown in Figure 6-6.

    Figure 6-6 Authorization Editor to define Security for the Login Page

    Description of Figure 6-6 follows
    Description of "Figure 6-6 Authorization Editor to define Security for the Login Page"

Step 5: Configuring the Application to Use ADF Security and the Login Page

In this step, you will use the Oracle ADF Security Wizard to configure authentication settings for the SRDemo application. All the options that you select are recorded in web.xml. To configure authentication settings, you must perform the following configuration tasks:

To configure the SRDemo application to use ADF Security and the login page, perform the following steps:

  1. In the Applications Navigator, select UserInterface.

  2. From the Tools menu, choose ADF Security Wizard. The ADF Security wizard will guide you through the configuration process.

  3. If needed, click Next to skip the Welcome page.

  4. Ensure that Enforce Authorization is selected. This option configures the adfAuthentication servlet and configures authorization rules (appropriate filters to allow for checking of the current user's permissions on the page).

  5. Click Next to move to the next page of the wizard.

  6. Choose Lightweight XML Provider. Oracle ADF Security authenticates users against a given resource provider. For the SRDemo we will use the lightweight resource provider system-jazn-data.xml that you copied while following the steps in the install.html file located in the sample files you downloaded.

  7. Click Next to display the next page of the wizard.

  8. On this page, set the Location to Application Repository, Default Realm to jazn.com, JAAS Mode to doAsPrivileged, and then click Next.

  9. On the login page, choose Form-Based Authentication (Figure 7-8). This specifies that the SRDemo application will use a form to facilitate authentication.

    There is no need to generate default pages for the login form and login error message (login.html and error.html) because we will be using the login form we built earlier in SRLoginADF.jspx.

  10. In the Login Page field, enter /infrastructure/SRLoginADF.jspx.

  11. In the Error Page field, you can also enter faces/infrastructure/SRLoginErrorPage.jsp, as shown in Figure 6-7.

    Figure 6-7 Form-Based Authentication Details

    Description of Figure 6-7 follows
    Description of "Figure 6-7 Form-Based Authentication Details"

  12. Click Next to display the final page of the wizard.

    This page defines resources within your application that should be secured, and specifies which J2EE security roles can access each resource. The adfAuthentication resource (the authentication servlet) is defined for you. You cannot edit or delete this resource, but you can specify the set of roles that may access this resource. One J2EE role, named oc4j-administrators, is selected by default, but we want any valid user to be able to access the adfAuthentication resource, so you will need to create another J2EE role, which you will name ValidUser, and grant access to this role.

  13. Remove the Web resource J2EE-Secured-Application, if it shows up.

  14. Click Manage Roles.

  15. Click Add, and enter the name ValidUser.

    Later on, you will map this J2EE role to one of the identity store roles, users, which you defined at the start of this lesson. This role maintains a list of every valid user. From a security perspective, allocating permissions to this role effectively defines an authenticated Public resource. That is, it would be available to all users without a need for the definition of specific permissions.

  16. Click OK. The ValidUser role should appear in the list.

  17. Click Close.

  18. Click the double arrow (Add All) to move everything in the Available Roles list to the Selected Roles list.

  19. This completes ADF Security wizard settings, so click Next and then Finish.

  20. You can now run the application's SRWelcome.jspx page and this should take you to the publicly accessible welcome page.

  21. Click the login link. This will take you to the login page you built in this chapter.

  22. Log in as a manager (sking). The contents of the RTP would normally be defined in a site administration page. This page will be built later.

    Note:

    Prior to creating the site administration, you can customize the login page by directly accessing the page URL as a user with Customize privilege on the page.

Step 6: Updating Web.xml to Call the New Login Page

The steps to update web.xml to call the new login page are as follows:

  1. In the Applications Navigator, expand the WEB-INF node and open the web.xml property palette (choose Properties from the right-click menu).

  2. Select Filter Mappings in the left panel and add a new filter mapping for the adfBindings Filter as shown Figure 6-8.

    Figure 6-8 New Filter Mappings for the adfBindings Filter

    new filter mapping
    Description of "Figure 6-8 New Filter Mappings for the adfBindings Filter"

    Make sure that the Servlet Name = Faces Servlet and that the Forward and Include dispatcher types are set.

  3. Click OK to save the changes to web.xml.

    Note:

    As the login page is also a JSPX page (and hence secured by ADF security) it must be defined as a public page. If the page is not defined as public then the container will continually redirect to the defined authentication point before allowing access to this page (which of course is this page resulting in a continuous loop).
  4. Right-click the SRLoginADF.jspx page in the application navigator and select Go to Page Definition. Confirm creation of the page definition file if it currently does not exist.

  5. Right-click the page definition file and select Edit Authorization.

  6. Grant View privilege to the anyone role, as shown in Figure 6-9.

    Figure 6-9 Authorization Editor

    Description of Figure 6-9 follows
    Description of "Figure 6-9 Authorization Editor"

  7. As the login page contains customizable portlets, the appropriate role must have customize privilege on the page.

Step 7: Running the Application

You can now run the application and test whether the login and error pages you created are displayed correctly. To do this, perform the following steps:

  1. Run the SRWelcome.jspx page.

  2. Click the login link. This displays the login page.

  3. Log in using a valid username and password.

    You are logged in to the demo application successfully.

  4. Log out from the application.

  5. To test whether the error page is displayed correctly, login using incorrect credentials three times. The error page is displayed.

Summary

In this chapter, you learned how to build an ADF Faces-based login page and configure the SRDemo application to use this login page. You can now enable administrators to customize the login page at run time. Chapter 9, "Building a Site Administration Page" describes the steps involved in enabling this type of customization.