Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0)

Part Number B25947-02
Go to Documentation Home
Home
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

30 Adding Security to an Application

This chapter describes how to use Oracle ADF Security in your web application to handle authentication and authorization on the Oracle Application Server. It also describes how to bypass Oracle ADF Security when you want to work strictly with container-managed security.

This chapter includes the following sections:

30.1 Introduction to Security in Oracle ADF Web Applications

Web application security can be provided by Oracle ADF Security. The Oracle ADF Security implementation is built upon a pluggable architecture that implements the Oracle Application Server Java Authentication and Authorization (JAAS) Provider for authentication and authorization:

First, you must configure the application to use a resource provider. The user data against which the login and passwords are authenticated is stored within a resource provider, such as a database or LDAP director. By editing the jazn.xml file, you choose an identity management provider for the OracleAS JAAS Provider. Read the following section to understand editing the jazn.xml file:

Then, you can configure the application's container to use Oracle ADF Security. This will allow you to use Oracle ADF Security for authentication and authorization. Alternatively, you can bypass Oracle ADF Security and use container-managed security. Read the following sections to understand how to configure authentication and create login and logout pages:

When you want to assign resources to particular users, you can work with Oracle ADF Model layer to enable authorization. If you choose not to use ADF authorization, you can still work with ADF authentication. Alternatively, you can integrate standard J2EE authorization with the Oracle ADF Model layer to restrict resources. The SRDemo application uses the latter approach. Read the following section to understand both approaches to implementing authorization:

Note:

When you want to understand the security features of OC4J, see the Oracle Containers for J2EE Security Guide in the Oracle Application Server documentation library. For example, the "Standard Security Concepts" chapter provides a useful overview of the JAAS security model.

30.2 Specifying the JAZN Resource Provider

If you wish to use the JAZN realm from either the lightweight XML resource provider (system-jazn-data.xml) or through the Oracle Internet Directory, you need to edit the jazn.xml file to select one of those providers.

Note: If you are working with another JAAS-compliant security provider, see your security provider's documentation.

30.2.1 How To Specify the Resource Provider

To use the JAZN realm from either the lightweight XML resource provider (system-jazn-data.xml) or through the Oracle Internet Directory (LDAP provider), you need to specify which provider you want your application to work with.

To specify the resource provider, you edit the provider environment descriptor in jazn.xml, located in the following directories.

  • For JDeveloper's embedded OC4J:

    <JDEV_HOME>/jdev/system/oracle.j2ee.10.1.3/embedded-oc4j/config directory

  • For JDeveloper's standalone OC4J:

    <JDEV_HOME>/j2ee/home/config directory

  • For Oracle Application Server:

    <OC4J_HOME>/j2ee/<instance_name>/config directory

To work with the XML-based provider, comment out the environment descriptor for LDAP:

<jazn xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation=
         "http://xmlns.oracle.com/oracleas/schema/jazn-10_0.xsd"
   schema-major-version="10"
   schema-minor-version="0"
   provider="XML" 
   location="./system-jazn-data.xml" 
   default-realm="jazn.com"
/>

<!--
<jazn 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:noNamespaceSchemaLocation=
         "http://xmlns.oracle.com/oracleas/schema/jazn-10_0.xsd"
   schema-major-version="10"
   schema-minor-version="0"
   provider="LDAP" 
   location="ldap://myoid.us.oracle.com:389"
/>
-->

To work with the LDAP provider, comment out the environment descriptor for XML:

<!--
<jazn 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation=
         "http://xmlns.oracle.com/oracleas/schema/jazn-10_0.xsd"
   schema-major-version="10"
   schema-minor-version="0"
   provider="XML" 
   location="./system-jazn-data.xml" 
   default-realm="jazn.com"
/>
-->

<jazn 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:noNamespaceSchemaLocation=
         "http://xmlns.oracle.com/oracleas/schema/jazn-10_0.xsd"
   schema-major-version="10"
   schema-minor-version="0"
   provider="LDAP" 
   location="ldap://myoid.us.oracle.com:389"
/>

30.2.2 What You May Need to Know About Oracle ADF Security and Resource Providers

Because Oracle ADF Security uses OracleAS JAAS, it relies on the LoginContext to provide the basic methods for authentication. LoginContext uses Login Modules, which are pluggable bits of code that handle the actual authentication. Oracle ADF Security also uses OracleAS JAAS Provider RealmLoginModule login module to perform standard user name/password type of authentication.

Oracle ADF Security can authenticate users against a given resource provider. The resource provider, such as a database or LDAP directory, contains the data against which the login and passwords are authenticated.

Specifically, Oracle ADF Security supports the use of Oracle Single Sign-On and Oracle Internet Directory (OID) to provide authentication. You should use OID (the LDAP-based provider) to provide identity management in production environments where scalability and manageability are important. In this case, you will need to administer the users through the LDAP administration tools provided with Oracle Containers for J2EE.

For more information on using OID, see the Oracle Identify Management Guide to Delegated Administration from the Oracle Application Server documentation library.

In addition, JDeveloper provides an XML-based resource provider (system-jazn-data.xml) that can be used for small scale applications or for development and testing purposes. This provider contains user, role, grant, and login module configurations.

30.3 Configuring Authentication Within the web.xml File

In many web-based applications, there may be a link to "protected" areas of the site that require knowing who the originator of the request is; in other words, access to the linked area requires an authenticated user. This can be accomplished dynamically with the adfAuthentication servlet or without ADF, using only J2EE container-managed authentication provided by OC4J. Either way, by configuring the container with security constraints, you prevent access to the server without an authenticated session.

Note:

The SRDemo application currently does not demonstrate Oracle ADF Security at the ADF Model layer. To understand how the SRDemo application handles authentication, see Section 30.3.1, "How to Enable J2EE Container-Managed Authentication".

Once the user is authenticated, the application can determine whether that user has privileges to access the resource as defined by any authorization constraint. You configure this constraint and set up users or roles for you application to recognize in the web.xml file.

For example, in the SRDemo application, three roles determine who gets access to perform what type of functions. Each user must be classified with one of the three roles: user, technician or manager. All of these criterion are implemented using container managed Form-based authentication supported by Oracle Application Server.

30.3.1 How to Enable J2EE Container-Managed Authentication

If your application contains pages that require a user to be authenticated against a data store in order to be accessed, you must declare the following in the web.xml configuration file:

  • <security-role> defines valid roles in the security context.

  • <login-config> defines the protocol for authentication, for example form-based or HTTPS.

  • <security-constraint> defines the resources specified by URL patterns and HTTP methods that can be accessed only by authorized users or roles.

  • <servlet> defines the servlet that provides authentication.

  • <servlet-mapping> maps the servlet to a URL pattern. The

  • <filter> defines the filter used to transform the content of the authentication request.

  • <filter-mapping> maps the filter to the file extensions used by the application. For details about the ADF binding filter, see Configuring the ADF Binding Filter.

Note:

When you insert an ADF Faces component into a JSF page for the first time, JDeveloper updates the web.xml file to define the ADF Faces servlet filter and ADF Faces resources servlet. For more details about the these servlet settings, see What Happens When You First Insert an ADF Faces Component.

The security roles that you define in the web.xml file identify the logical names of groups of users that your application recognizes. You will create security constraints in order to restrict access to particular web pages based on whether the authenticated user belongs to the authorized role or not.

To specify security roles for J2EE container-managed security:

  1. In the Navigator, expand your JSP project, right-click the web.xml file and choose Properties. The web.xml file resides in the WEB-INF folder of your project.

  2. To add the security role definition, select Security Roles on the left panel of the Web Application Deployment Descriptor editor and click Add.

    The roles you enter here must match roles from your data store. For example, if you are using the XML-based provider (as defined with system-jazn-data.xml), you would enter the value of <name> for any of the defined <roles> that need to be authenticated. Additionally, if you configure OC4J to use security role mapping, the role names must also match the roles defined in the <security-role-mapping> element of the orion-web.xml configuration file.

  3. Save all changes and proceed to create the login configuration, as described below.

Figure 30-1 shows the web.xml editor with the Security Roles definition displayed. In the SRDemo application, three security roles are defined.

Figure 30-1 Web Application Deployment Descriptor Dialog, Security Roles Panel

Security roles in Deployment Descriptor editor.

Before configuring the login configuration, you should already have created a login web page and the optional login error page. For details, see Section 30.5, "Creating a Login Page".

To create a login configuration for J2EE container-managed security:

  1. In the Navigator, expand your JSP project, right-click the web.xml file and choose Properties. The web.xml file resides in the WEB-INF folder of your project.

  2. To create a login configuration, select Login Configuration on the left panel of the editor. For example, to use form-based authentication, you would select Form-Based Authentication, and enter the name of the file used to render the login and login error page, for example login.jspx and loginerror.jspx. For further details, see Section 30.5.1, "Wiring the Login and Error Pages".

  3. Save all changes and close the Web Application Deployment Descriptor editor.

Figure 30-2 shows the web.xml editor with the Login Configuration definition displayed.

Figure 30-2 Web Application Deployment Descriptor Dialog, Login Configuration Panel

Login configuration in Deployment Descriptor editor.

To create security constraints for J2EE container-managed security:

  1. In the Navigator, expand your JSP project, right-click the web.xml file and choose Properties. The web.xml file resides in the WEB-INF folder of your project.

  2. To add the security constraint definition, select Security Constraints on the left panel of the editor, and at the bottom of the panel click New.

  3. To add a new Web Resource, on the Constraints page, click Add.

    Tip: Because the security constraint is specified as a URL, the web resource name you supply can be based on your application's database connection name. For example, if your database connection is MyConnection, then you might type jdbc/MyConnection for the web resource name.

  4. To specify the URL pattern of your client requests, click the web resource name you just specified, select URL Patterns, and click Add. Type a forward slash (/) to reference a JSP login page located at the top level relative to the web application folder.

  5. To specify authorized security roles, select the Authorization tab. Select the security roles that require authentication. The roles available are the roles you configured in step 2.

  6. To specify transport guarantee, select the User Data tab. Select the type of guarantee to use.

  7. Save all changes and close the Web Application Deployment Descriptor editor.

Figure 30-3 shows the web.xml editor with a Security Constraint definition displayed.

Figure 30-3 Web Application Deployment Descriptor Dialog, Security Constraints Panel

Security contraints in Deployment Descriptor editor.

30.3.2 What Happens When You Use Security Constraints without Oracle ADF Security

Example 30-1 shows sample definitions similar to the ones that your web.xml file should contain when you have finished configuring J2EE container-managed security.

Example 30-1 J2EE Security Enabled in the SRDemo Application web.xml File

<security-constraint>
    <web-resource-collection>
      <web-resource-name>ALL Manager</web-resource-name>
      <url-pattern>faces/app/management/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
      <web-resource-name>AllStaff</web-resource-name>
      <url-pattern>faces/app/staff/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>technician</role-name>
      <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
      <web-resource-name>SRDemo Sample</web-resource-name>
      <url-pattern>faces/app/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
       <role-name>user</role-name>
          <role-name>technician</role-name>
          <role-name>manager</role-name>
       </auth-constraint>
  </security-constraint>
  <login-config>
     <auth-method>FORM</auth-method>
     <form-login-config>
        <form-login-page>infrastructure/SRLogin.jspx</form-login-page>
        <form-error-page>infrastructure/SRLogin.jspx</form-error-page>
     </form-login-config>
  </login-config>
  <security-role>
     <description>Customers of ACME corp</description>
     <role-name>user</role-name>
  </security-role>
  <security-role>
     <description>Employees of ACME corp</description>
     <role-name>technician</role-name>
  </security-role>
  <security-role>
     <description>The boss</description>
     <role-name>manager</role-name>
  </security-role>

When the user clicks a link to a protected page, if they are not authenticated (that is, the authenticated user principal is not currently in SecurityContext), the OC4J security servlet is called and the web container invokes the login page defined by the deployment descriptor <form-login-config> element.

Once a user submits their user name and password, that data is compared against the data in a resource provider where user information is stored, and if a match is found, the originator of the request (the user) is authenticated. The user name is then stored in SecurityContext, where it can be accessed to obtain other security related information (such as the group the user belongs to) in order to determine authorization rights.

The web.xml deployment descriptor supports declarative security through <security-constraints> that specify the resources available to the authenticated users of the application. Whether or not the user is permitted to access a web page depends on its membership in a role identified in the <auth_constraint> element. The application calls the servlet method isUserInRole() to determine if a particular user is in a given security role. The <security-role> element defines a logical name of the roles based on the same names defined by the JAZN realm in the system-jazn-data.xml file.

30.3.3 How to Enable Oracle ADF Authentication

For web-based applications, you can configure a security constraint against the adfAuthentication servlet within the web.xml file. This constraint prevents access to the servlet without an authenticated session. As long as the link to the protected area contains the URL pattern defined in the constraint, the web container will invoke the login page if the user is not authenticated.

Note:

The adfAuthentication servlet is optional and allows dynamic authentication, that is, if the user has not yet logged in and the page being accessed needs authorization, then the user will be prompted to log in. The servlet take an optional parameter success_url. If success_url is specified, then after successfully logging in, the user is directed to the requested page. If success_url is not specified, then after successful login, the servlet directs the user back to the page from which the login was initiated.

To configure web.xml for Oracle ADF Security:

  1. In the Navigator, expand your JSP project, right-click the web.xml file and choose Properties. The web.xml file resides in the WEB-INF folder of your project.

  2. Define Security Roles, Login Configuration, and Security Constraints as you normally would. (See above procedures.)

  3. To create the <servlet> element for the ADF authentication servlet, select Servlets/JSP on the left panel of the editor and click New. Enter the following:

    Servlet Name: adfAuthentication

    Servlet Class: oracle.adf.share.security.authentication.AuthenticationServlet

    To add an initialization parameter that contains the URL for the resulting page if authentication succeeds, select Initialization Parameters and click Add. If you do not enter a URL, the user will return to the current page.

  4. To create a servlet mapping, select Servlet Mapping on the left panel of the editor, and click Add. Enter the following:

    URL Pattern: /adfAuthentication/*

    Servlet Name: adfAuthentication

  5. Save all changes and close the Web Application Deployment Descriptor editor.

Figure 30-3 shows the web.xml editor with the Servlet Mapping definition displayed for the adfAuthentication servlet.

Figure 30-4 Web Application Deployment Descriptor Dialog, Servlet Mapping Panel

ADF servlet mapping in the Deployment Descriptor editor.

30.3.4 What Happens When You Use Security Constraints with Oracle ADF

Example 30-2 shows sample definitions similar to the ones that your web.xml file should contain.

Example 30-2 Oracle ADF Security Enabled in a Sample web.xml File

<servlet>
  <servlet-name>adfAuthentication</servlet-name> <servlet-class>oracle.adf.share.security.authentication.                              AuthenticationServlet</servlet-class>
  <init-param>
    <param-name>sucess_url</param-name>
    <param-value>inputForm.jsp</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>adfAuthentication</servlet-name>
  <url-pattern>/adfAuthentication/*</url-pattern>
</servlet-mapping>
<security-constraint>
  <web-resource-collection>
    <web-resource-name>adfAuthentication</web-resource-name>
    <url-pattern>/adfAuthentication</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>user</role-name>
  </auth-constraint>
</security-constraint>
<login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
    <form-login-page>login.jspx</form-login-page>
    <form-error-page>login.jspx</form-error-page>
  </form-login-config>
</login-config>
<security-role>
  <role-name>user</role-name>
</security-role>

When the user clicks a link to a protected page, if they are not authenticated (that is, the authenticated user principal is not currently in SecurityContext), the Oracle ADF Security Login Servlet is called and the web container invokes the login page.

Once a user submits their user name and password, that data is compared against the data in a resource provider where user information is stored, and if a match is found, the originator of the request (the user) is authenticated. The user name is then stored in SecurityContext, where it can be accessed to obtain other security related information (such as the group the user belongs to) in order to determine authorization rights.

Because Oracle ADF Security implements OracleAS JAAS, authentication also results in the creation of a JAAS Subject, which also represents the originator of the request.

30.4 Configuring the ADF Business Components Application to Use Container-Managed Security

When you want to work with security in an Oracle ADF Business Components application, the ADF Business Components application module must be enabled to recognize the authenticated user. This will permit the application to create the application module based on the presence of an authenticated user. If the user attempts to login and is not authenticated, no application module will be created for the session.

30.4.1 How to Configure Security in an Oracle ADF Business Components Application

To enable security in an Oracle ADF Business Components application, you must edit the jbo.security.enforce property of the application modules configuration (maintained in the bc4j.xcfg file). The jbo.security.enforce property set to Must specifies that an authenticated user must be logged in before the application module will be created. This is a requirement for any business components application that will work with container-managed security.

To configure security for Oracle ADF Business Components:

  1. In the Application Navigator, expand the data model project and located the application module node.

  2. Right-click the application module node and choose Configurations.

  3. In the Configuration Manager, select the configuration for your application and click Edit.

  4. In the Oracle Business Components Configuration dialog, select the Properties tab.

    The dialog display the full list of ADF Business Components configuration properties. The security properties begin with jbo.security.

  5. Scroll to locate the jbo.security.enforce property and enter the value Must.

  6. Click OK to close the dialogs and save the configuration changes.

Figure 30-6 shows the application module configuration SRServiceLocal and security property as they appear in the SRDemo application for ADF Business Components.

Figure 30-5 ADF BC Configuration Dialog, Properties Panel

Sample login page from the SRDemo application.

In order to use the JAZN realm in an ADF Business Components application, you must export the BC4J Security library to your user interface project. This will ensure that the jazn.jar is available to the user interface project at runtime. Without this library defined, an exception such as NullPointerException in JboJAZNUserManager.isUserInRole() will be returned when your application attempts to verify the logged in user.

To add required libraries for ADFBC Security to the user interface project:

  1. In the Application Navigator, right-click the user interface project and choose Project Properties.

  2. In the Project Properties dialog, select Libraries to view the list of available libraries.

  3. Scroll to locate BC4J Security and make sure that Export is enabled.

  4. Click OK to close the dialog and save the setting.

Figure 30-6 shows the BC4J Security library as it should appear for the user interface project.

Figure 30-6 Project Properties Dialog, Libraries Panel

Sample login page from the SRDemo application.

30.4.2 What Happens When You Configure Security in an ADF Business Components Application

The jbo.security.enforce property in the ADF Business Components application module's configuration settings when set to Must requires the application module to obtain an authenticated user principal from the SecurityContext before the application module is created for the specified configuration.

30.4.3 What You May Need to Know About the ADF Business Components Security Property

The security mechanism provided by ADF Business Components can be combined with ADF Security when you want to want to configure security constraints against the adfAuthentication servlet. You enable ADF Security when you want to grant authorization permissions to ADF binding objects in the application. For details about the authorization features provided by ADF security, see Section 30.7, "Implementing Authorization Using Oracle ADF Security".

Tip:

Starting in JDeveloper 10.1.3.1 maintenance release, you need only set the ADF Security property authorizationEnforce to true and you will automatically enable security in an ADF Business Components application. In this case, the jbo.security.enforce property is not required.

When you enable ADF Security in an ADF Business Components application, the application module obtains the principal from the security context under the ADF context instead of the JAAS security context. For details about enabling ADF servlet authentication, see Section 30.3.3, "How to Enable Oracle ADF Authentication".

30.5 Creating a Login Page

The login page for a web application should use the J2EE security container login method j_security_check as a method that the form posts. Figure 30-7 shows a sample login page from the SRDemo application.

Figure 30-7 Sample Login Page from the SRDemo Application

Sample login page from the SRDemo application.

CAUTION:

When you create the login page, you may use JSP elements and JSTL tags. Your page can be formatted as a JSFX document, but due to a limitation in relation to JSF and container security, JSF components cannot be used.

To create a web page for the login form:

  1. With the user interface project selected, open the New Gallery and select JSP from the Web Tier - JSP category. Do NOT select the Web Tier - JSF category to create a JSPX document as a login form.

  2. In the Create JSP wizard, choose JSPX Document type for the JSP file type. The wizard lets you create a JSPX document without using managed beans.

  3. On the Tag Libraries page of the wizard, select All Libraries and add JSTL Format 1.1 and JSTL Core 1.1 to the Selected Libraries list.

  4. Click Finish to complete the wizard and add the JSPX file to the user interface project.

  5. In the Component Palette, select the JSTL 1.1 FMT page, and drag SetBundle into the Structure window for the JSPX document so it appears above the title element.

  6. In the Insert SetBundle dialog, set BaseName to the package that contains the resource bundle for the page. For example, in the SRDemo application, it is oracle.srdemo.view.resources.UIResources.

  7. Optionally, drag Message onto the title element displayed in the Structure window. Double-click the Message element and set the key property to the resource bundle's page title key. For example, in the SRDemo application, the key is srlogin.pageTitle. Delete the string title leftover from the page creation.

  8. In the Component Palette, select the HTML Forms page and drag Form inside the page body. In the Insert Form dialog, set the action to j_security_check and set the method to post.

  9. Drag Text Field for the user name into the form and set the name to j_username.

  10. Drag Password Field into the form and name it j_password.

  11. Drag Submit Button into the form with label set to Sign On.

  12. In the Component Palette, again select the JSTL 1.1 FMT page, and drag two Message tags into the form so they appear beside the input fields. Set their key properties. For example, in the SRDemo application, the resource keys are srlogin.password and srlogin.username.

Example 30-3 shows the source code from the SRDemo application's login page. This JSPX document uses only HTML elements and JSTL tags to avoid conflicts with the security container when working with JSF components. The security check method appears on the <form> element and the form contains input fields to accept the user name and password. These fields assign the values to the container's login bean attributes j_username and j_password, respectively.

Example 30-3 Sample Source from SRLogin.jspx

<html>
    <head>
      <meta http-equiv="Content-Type"
            content="text/html; charset=windows-1252"/>
      <fmt:setBundle basename="oracle.srdemo.view.resources.UIResources"/>
      <title>
        <fmt:message key="srdemo.login"/>
      </title>
    </head>
    <body>
        ... omitting the "number of attempts" checking logic ... 
        <form action="j_security_check" method="post">
          <table cellspacing="3" cellpadding="2" border="0" width="100%">
            <tr>
              <td colspan="3">
                <img height="69" width="340"
                     src="/SRDemo/faces/images/SRBranding.gif"
                     alt="SRDemo Logo"/>
                <hr/>
              </td>
            </tr>
            <tr>
              <td colspan="3">
                <h1>
                  <fmt:message key="srlogin.pageTitle"/>
                </h1>
              </td>
            </tr>
            <tr>
              <td colspan="3">
                <c:if test="${sessionScope.loginAttempts >0}">
                  <h3><fmt:message key="srdemo.badLogin"/></h3>
                </c:if>
              </td>
            </tr>
            <tr>
              <td>&amp;nbsp;</td>
              <td> </td>
              <td rowspan="7">
                <table border="1" cellpadding="5">
                  <tr>
                    <td>
                      <fmt:message key="srlogin.info"/>
                    </td>
                  </tr>
                </table>
              </td>
            </tr>
            <tr>
              <td>&amp;nbsp;</td>
            </tr>
            <tr>
              <td width="120">
                <b><fmt:message key="srlogin.username"/></b>
              </td>
              <td>
                <input type="text" name="j_username"/>
              </td>
            </tr>
            <tr>
              <td width="120">
                <b><fmt:message key="srlogin.password"/></b>
              </td>
              <td>
                <input type="password" name="j_password"/
              </td>
            </tr>
            <tr>
              <td> </td>
              <td>
                <input type="submit" name="logon" value="Sign On"/>
              </td>
            </tr>
            <tr>
            </tr>
              <td>&amp;nbsp;</td>
            <tr>
              <td>&amp;nbsp;</td>
            </tr>
            <tr>
              <td>&amp;nbsp;</td>
            </tr>
            <tr>
              <td colspan="3">
                <hr/>
              </td>
            </tr>
          </table>
        </form>
      </c:if>
    </body>
</html>

30.5.1 Wiring the Login and Error Pages

To allow the web container to perform authentication, the web.xml file must contain the login configuration information that specifies the page to display for log in and another page to display when log in fails because the user could not be authenticated.

To configure how login is to be handled:

  1. In the Application Navigator, locate web.xml in the WEB-INF folder.

  2. Right-click web.xml and choose Properties.

  3. In the Web Application Deployment Descriptor dialog, select Login Configuration.

  4. Choose Form-Based Authentication and enter the path name for both the login and error page. The path specified for the login page and error page is relative to the document root that will be used to authenticate the user. For example, in the SRDemo application, the path infrastructure/SRLogin.jspx is used for both the login and error page.

Figure 30-8 shows the web.xml editor with the Login Configuration definition displayed.

Figure 30-8 Web Application Deployment Descriptor Dialog, Login Configuration Panel

Login configuration in the Deployment Descriptor editor.

30.5.2 What Happens When You Wire the Login and Error Pages

When you define the web.xml login configuration information, JDeveloper creates these definitions:

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>infrastructure/SRLogin.jspx</form-login-page>
      <form-error-page>infrastructure/SRLogin.jspx</form-error-page>
    </form-login-config>
  </login-config>

Because you selected Form-based authentication, to specify user-written HTML Form for authentication, the page servlet will look for the JSP page you specified to authenticate the user. The JSP page must return an HTML page containing a Form that conforms to a specific naming convention. Similarly, when authentication fails, the servlet will look for a page to display. In the SRDemo application, the same page appears for both cases, though you could have defined different pages.

Example 30-3 shows the conventions of that permit the HTML Form to invoke the authentication servlet. Specifically, the form must specify three pieces of information:

  1. <form action="j_security_check" method="post"> to invoke the security check method j_security_check on the container's login bean.

  2. <input type="text" name="j_username"/> to assign the username value to the container's login bean attribute j_username.

  3. <input type="password" name="j_password"/> to assign the password value to the container's login bean attribute j_password.

Please note that the value of the login bean attributes must be retuned by the HTML Form with the exact names shown. In a JSF JSP page, a JSF form does not guarantee this. Therefore, Oracle recommends that you use a JSP document page in order to use the HTML Form to preserve the login bean attribute names.

30.6 Creating a Logout Page

The logout page may be called from the global logout button that appears on any page that includes the global menu page. The purpose of the logout page is to provide a prompt for the user to confirm that they want to quit. If the user chooses to log out, their session is invalidated and then they are redirected back to the application's welcome page. They will have to log in again to continue the application. Figure 30-9 shows the logout page from the SRDemo application.

Figure 30-9 Sample Logout Page from SRDemo Application

Navigator showing basic model project.

To create the logout page:

  1. With the user interface project selected, open the New Gallery and select JSF JSP from the Web Tier - JSF category. In this case, it is acceptable to use JSF components.

  2. In the Create JSF JSP wizard, choose JSP Document type for the JSF JSP file type. In this case, you want to create a JSPX document that will use JSF components.

  3. On the Component Binding page, do not create a managed bean.

  4. On the Tag Libraries page of the wizard, add ADF Faces Components and ADF Faces HTML to the Selected Libraries list.

  5. Click Finish to complete the wizard and add the JSPX file to the user interface project.

  6. In the Component Palette, select the ADF Faces Core page, and drag the components Document, Form, and PanelPage so that PanelPage appears nested inside Form, and Form appears nested inside Document.

  7. Next construct the PanelPage container for the command buttons by dragging the components PanelBox, PanelHeader, PanelButtonBar so that PanelButtonBar appears nested inside PanelHeader, and PanelHeader appears nested inside PanelBox. All should be nested inside PanelPage.

  8. To create the buttons that give the user the choice whether to logout or not, drag two CommandButton components inside the PanelButtonBar.

  9. The first button should provide the logout function. You can wire it separately by creating a managed bean. For details, see Section 30.6.1, "Wiring the Logout Action".

  10. The second button should invoke an action GlobalHome to direct the user to the desired page. This action will be defined in the faces-config.xml file with a navigation rule.

Example 30-4 shows the source code from the SRDemo application's logout page. This JSPX document has no restriction on using JSF components because the page has no interaction with the security container. The action to invoke the logout function appears on the <af:commandButton> with the logout label.

Example 30-4 Sample Source from SRLogout.jspx

<af:form>
      <af:panelPage title="#{res['srlogout.pageTitle']}">
        <!--Page Content Start-->
        <af:panelBox>
          <af:panelHeader text="#{res['srlogout.subTitle']}"
                          messageType="warning">
            <af:outputText value="#{res['srlogout.text']}"/>
            <af:panelButtonBar>
              <af:commandButton text="#{res['srlogout.logout.label']}"
                                action="#{backing_SRLogout.logoutButton_action}"/>
              <af:commandButton text="#{res['srlogout.goBack.label']}"
                                action="GlobalHome"/>
            </af:panelButtonBar>
          </af:panelHeader>
        </af:panelBox>
        <!-- Page Content End -->
        ... omitting facets related to the visual design of the page ...
      </af:panelPage>
</af:form>

30.6.1 Wiring the Logout Action

To handle the logout action, the JSPX document can use a managed bean with properties that correspond to the logout page's logout command button.

To handle the logout action:

  1. In the open logout page, double-click the command button that you reserved for the logout action.

  2. In the Action property dialog, leave Method Binding selected and click New to define the Managed Bean class.

  3. In the Create Managed Bean dialog, specify the new class file name for the managed bean and enter the name of the managed bean to register with the faces-config.xml file.

  4. In the Action property dialog, click New to name the method that you will implement in the managed bean class to return a string that sets the component's outcome value.

    Figure 30-10 shows the Action property dialog with the managed bean backing_SRLogout and the method logoutButton_action() entered.

  5. Figure 30-10 Action Binding Dialog for Logout CommandButton

    Backing bean method definition in Action dialog.
  6. In the generated .java file, implement the method handler for the command button that will redirect the user back to an appropriate page. See Example 30-5 for a sample.

Warning:

If your application calls the invalidate() method on the HTTP Session to terminate the current session at logoff time, you must use a "Redirect" to navigate back to a home page to require accessing an ADF Model binding container. The redirect to a databound page ensures that the ADF Binding Context gets created again after invalidating the HTTP Session.

Example 30-5 shows the method handler from the SRDemo application logout page's managed bean. The logoutButton_action() method invalidates the session and redirects to the home page. The security container will prompt the user to reauthenticate automatically.

Example 30-5 Sample Source from SRLogout.java

public String logoutButton_action() throws IOException{
    ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
    HttpServletResponse response = (HttpServletResponse)ectx.getResponse();
    HttpSession session = (HttpSession)ectx.getSession(false);
    session.invalidate();
    
    response.sendRedirect("SRWelcome.jspx");
    return null;
  }

30.6.2 What Happens When You Wire the Logout Action

When you define the action property for the command button, JDeveloper updates the Logout.jspx page source code with the name of the managed bean and bean method to invoke:

<af:commandButton text="#{res['srlogout.logout.label']}"
               action="#{backing_SRLogout.logoutButton_action}"/>

and, JDeveloper updates the faces-config.xml file to define the managed bean:

<managed-bean>
     <managed-bean-name>backing_SRLogout</managed-bean-name>
     <managed-bean-class>oracle.srdemo.view.backing.SRLogout</managed-bean-class>
     <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Once a user clicks the logout button, the JSF controller identifies the corresponding class file from the Faces configuration file and passes the name of the action handler method to the managed bean. In turn, the action handler, shown previously in Example 30-5, invalidates the session and redirects to the home page.

30.7 Implementing Authorization Using Oracle ADF Security

Authorization provides a way to restrict access to a resource based on the user attempting access. Oracle ADF Security implements OracleAS JAAS for authorization of security-aware resources.

Oracle ADF Security provides another level of granularity, allowing object instance access control based on Java Permissions using JAAS. Specifically, certain Oracle ADF Model layer objects are "security-aware," meaning that there are pre-defined component-specific permissions that a developer can grant for a given resource.

Note:

The SRDemo application currently does not demonstrate Oracle ADF Security at the ADF Model layer. To understand how the SRDemo application handles authorization, see Section 30.8, "Implementing Authorization Programmatically".

The following Oracle ADF objects are security-aware as defined by the page definition file associated with each databound web page:

You set grants on these objects by defining which authenticated users or roles have permission to perform a given action on the object (called a resource). Grantees, which are roles, users, or groups defined as principals are mapped to permissions. Permissions are permission to execute a specific action against a resource, as defined by Oracle ADF Security classes (see the Oracle ADF Javadoc for details). Grants are aggregated. That is if a group's role is granted permissions, and a user is a member of that group, then the user also has those permissions. If no grant is made, then access by the role, user, or group is denied.

Table 30-1 shows permissions you can grant on binding containers, iterator bindings, attribute-level bindings (for example, table, list, boolean, and attribute-value bindings), and method bindings. You use the Authorization Editor to grant permissions for users on the Oracle ADF objects created at runtime from the page definition file.

Table 30-1 Oracle ADF Security Authorization Permissions

ADF Model Object Defined Actions Affect on Components in the User Interface

Binding Container for a web page

grant - can administer the permissions on the page

On pages that allow runtime customization, any link or button configured to set access controls will be disabled for users not granted this permission.

 

edit - can edit content on the page

If a user is granted permission for the view action, but not for the edit action, then any data in input text boxes will display as read only.

 

personalize - allows the user customization of the page

On pages that allow runtime customization, any link or button configured to put the page into personalization mode will be disabled for users not granted this permission.

 

view - can view the page

A user not granted this permission will be shown an authorization error.

Iterator Binding

read - can read the returned rows

All rows of data will be returned. However, you can limit what can be displayed or updated by placing grants on the individual attribute bindings.

 

update - can update data in a row

If the Commit operation is dropped as a command button from the Data Control Palette, the button will be disabled for users who were not granted this permission. Instead of limiting updates to an entire row, you can instead limit the ability to update individual attributes.

 

create - can create a new row

If the Create operation is dropped as a command button from the Data Control Palette, the button will be disabled for any users that were not granted this permission.

 

delete - can delete a row

If the Delete operation is dropped as a command button from the Data Control Palette, the button will be disabled for any users that were not granted this permission.

Method Action Binding

invoke - the method can execute

If the method is bound to a command button, that button will be disabled for any users that were not granted this permission. If the method is invoked implicitly, the method will only execute for users granted this permission.

Attribute-level Bindings

read - can read the attribute's value

The value for the attributes will be displayed.

 

update - can update the attribute 's value

Any data in input text boxes will display as read only for users who were not granted this permission.


Before you can implement Oracle ADF authorization, you must first:

30.7.1 Configuring the Application to Use Oracle ADF Security Authorization

You must first configure the application to use Oracle ADF Security before you can work with ADF authorization in your application.

30.7.1.1 How to Configure Oracle ADF Security Authorization

To enable Oracle ADF Security authorization, you create a configuration file named adf-config.xml that sets the application's container to use Oracle ADF Security. The file initializes the ADFContext and SecurityContext.

To configure an application to use Oracle ADF Security:

  1. Right-click on the project for which security is needed and choose New.

  2. In the New Gallery, select the XML category.

    If XML is not displayed, use the Filter By list at the top to select All Technologies.

  3. In the Items list, select XML Document and click OK.

  4. Name the file adf-config.xml, save it in the <application_name>/.adf/META-INF directory, and click OK.

    The file opens in the source editor.

  5. Replace the generated code with the following:

    <?xml version="1.0" encoding="windows-1252" ?> 
    <adf-config xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance " 
        xsi:schemaLocation=" http://xmlns.oracle.com/adf/config 
        ../../../../../bc4jrt/src/oracle/adf/share/config/schema/config.xsd" 
        xmlns=" http://xmlns.oracle.com/adf/config " 
        xmlns:sec=" http://xmlns.oracle.com/adf/security/config ">
       <sec:adf-config-child xmlns=" http://xmlns.oracle.com/adf/security/config "> 
         <JaasSecurityContext
            initialContextFactoryClass="oracle.adf.share.security.
                 JAASInitialContextFactory" 
            authorizationEnforce="true" 
            jaasProviderClass="oracle.adf.share.security.providers.jazn.
                 JAZNSecurity Context" > 
        </JaasSecurityContext>
       </sec:adf-config-child>
    </adf-config>
    
  6. Save and close the file.

30.7.1.2 What Happens When You Configure An Application to Use Oracle ADF Security

The authorizationEnforce parameter in the <JaasSecurityContext> element set to true will allow the authenticated user principals to be placed into ADF SecurityContext once the user is authenticated.

Tip:

If you want to run the application without using Oracle ADF Security, simply set the authorizationEnforce parameter to false.

30.7.1.3 What You May Need to Know About the Authorization Property

Because security can be turned on and off, it is recommended that an application should determine this property setting before invoking an authorization check. The application can check if Oracle ADF Security is enabled by checking the authorization property setting. This is exposed through the isAuthorizationEnabled() method of the SecurityContext under the ADFContext. For example:

if (ADFContext.getCurrent().getSecurityContext().isAuthorizationEnabled()) 
  {
    Permission p = new RegionPermission("view.pageDefs.page1PageDef", "Edit");
    AccessController.checkPermission(p);
    // do the protected action
  } catch (AccessControlException ace) {
    // do whatever's appropriate on an access denied
}

Note:

Starting in JDeveloper 10.1.3.1 maintenance release, you need only set the ADF Security property authorizationEnforce to true and you will automatically enable security for ADF Business Components applications. In this case, the jbo.security.enforce property is not required. To understand how ADF Business Components enforces security, see Section 30.4, "Configuring the ADF Business Components Application to Use Container-Managed Security".

30.7.2 Setting Authorization on ADF Binding Containers

You use the Authorization Editor to grant permissions for users on the binding container as it is defined by the entire page definition. See Table 30-1 for details about available Oracle ADF permissions.

To grant permissions on the binding container using the Authorization Editor:

  1. Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.

  2. In the Structure window, right-click the root node, PageDef, and choose Edit Authorization.

  3. The Authorization Editor shows the pre-defined permissions for the binding container, along with the principals (roles and users) as defined by your resource provider.

    Click Help or press F1 for more help on using this dialog.

30.7.3 Setting Authorization on ADF Iterator Bindings

You use the Authorization Editor to grant permissions for users on iterator bindings. See Table 30-1 for details about available Oracle ADF permissions.

To grant permissions on iterators using the Authorization Editor:

  1. Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.

  2. In the Structure window, expand the executables node.

  3. Right-click on the iterator you wish to grant a permission for and choose Edit Authorization.

  4. The Authorization Editor shows the pre-defined permissions for the iterator, along with the principals (roles and users) as defined by your resource provider.

    Click Help or press F1 for more help on using this dialog.

30.7.4 Setting Authorization on ADF Attribute and MethodAction Bindings

You use the Authorization Editor to grant permissions for users on attribute and method action bindings.

Note that permissions granted on an attribute reflect the ability to execute operations such as Create, Delete, and Commit. Therefore, do not set authorization on the operations, but instead on the attribute or iterator. See Table 30-1 for details about Oracle ADF permissions.

To grant permissions on attribute and method bindings using the Authorization Editor:

  1. Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.

  2. In the Structure window, expand the bindings node.

  3. Right-click on the attribute or method action binding you wish to grant a permission for and choose Edit Authorization.

  4. The Authorization Editor shows the pre-defined permissions for the attribute or method action binding, along with the principals (roles and users) as defined by your resource provider.

    Click Help or press F1 for more help on using this dialog.

30.7.5 What Happens When Oracle ADF Security Handles Authorization

When a user attempts to execute an action against a resource which has a defined grant, Oracle ADF Security checks to see if the user is a principal defined in the grant. If the user is not yet authenticated, the application displays the login page or form. If the user has been authenticated, and does not have permission, a security error is displayed.

Example 30-6 shows grants for the attribute binding and method binding if you are using the Oracle JAZN lightweight XML provider, these grants are written in the system-jazn-data.xml file. Note that in these grants, the role users has been granted a RowSetPermission to create, read, and update the attributes of the bound collection EmployeesView1, and also an AttributePermission to read the DepartmentID attribute value.

Example 30-6 Sample system-jazn-data.xml File Oracle ADF Permissions

<grant>
  <grantee>
    <principals>
      <principal>
        <realm-name>jazn.com</realm-name>
        <type>role</type>
        <class>oracle.security.jazn.spi.xml.XMLRealmRole</class>
        <name>jazn.com/users</name>
      </principal>
    </principals>
  </grantee>
  <permissions>
    <permission>
      <class>oracle.adf.share.security.authorization.RowSetPermission</class>
      <name>EmployeesView1</name>
      <actions>create,read,update</actions>
    </permission>
    <permission>
      <class>oracle.adf.share.security.authorization.AttributePermission</class>
      <name>EmployeesView1.DepartmentId</name>
      <actions>read</actions>
    </permission>
  </permissions>
</grant>

Users or roles are those already defined in your resource provider.

30.8 Implementing Authorization Programmatically

You can set authorization policies against resources and users. For example, you can allow only certain groups of users the ability to view, create, or change certain data or invoke certain methods. Or, you can prevent components from rendering based on the group a user belongs to. Because the user has been authenticated, the application can determine whether or not to allow that user access to any object that has an authorization restraint configured against it.

The application can reference roles programmatically to determine whether a specific user belongs to a role. In the SRDemo application this is accomplished using the method isUserInRole() defined by the FacesContext interface (and also available from the HttpServletRequest interface).

The SRDemo application uses three core roles to determine who will have access to perform specific functions. Each user is classified with by the roles: user, technician, or manager. The remoteUser value (obtained from the Faces Context) matches the email address in the SRDemo application's USERS table. These criteria are implemented using container-managed, Form-based authentication provided by Oracle Application Server as described in Section 30.3.1, "How to Enable J2EE Container-Managed Authentication".

30.8.1 Making User Information EL Accessible

Once the security container is set up, performing authorization is a task of:

  • Reading the container security attributes the first time the application references it

  • Making the key security information available in a form that can be accessed through the expression language

To accomplish this, the JSF web application can make use of a managed bean that is registered with session scope. The managed beans are Java classes that you register with the application using the faces-config.xml file. When the application starts, it parses this configuration file and the beans are made available and can be referenced in an EL expression, allowing access by the web pages to the bean's content.

For detailed information about working with managed beans, see Section 17.2, "Using a Managed Bean to Store Information".

This sample from SRList.jspx controls whether the web page will display a button that the manager uses to display an edit page.

<af:commandButton text="#{res['srlist.buttonbar.edit']}"
                  actionListener="#{bindings.setCurrentRowWithKey.execute}"
                  action="Edit"
                  rendered="#{userInfo.manager}">
   <af:setActionListener from="#{row.rowKeyStr}"
                         to="#{processScope.rowKeyStr}"/>
   <af:setActionListener from="#{'GlobalHome'}"
                         to="#{userState.returnNavigationRule}"/>
</af:commandButton>

This sample from SRCreateConfirm.jspx controls whether the web page will display a user name based on the user's authentication status.

<f:facet name="infoUser">
     <!-- Show the Logged in user -->
     <h:outputFormat value="#{res['srdemo.connectedUser']}"
                     rendered="#{userInfo.authenticated}" escape="false">
            <f:param value="#{userInfo.userName}"/>
     </h:outputFormat>
</f:facet>

30.8.1.1 Creating a Class to Manage Roles

The managed bean's properties allow you to invoke methods in a class that contains the code needed to validate users and to determine the available roles. This class should be created before you create the managed bean so you know the property names to use when you define the managed bean.

To create the Java class:

  1. In the New Gallery select the General category and the Java Class item.

  2. In the Create Java Class dialog, enter the name of the class and accept the defaults to create a public class with a default constructor.

Example 30-7 shows the key methods that the SRDemo application implements:

Example 30-7 SRDemo Application UserInfo.java Sample

/**
 * Constructor
 */
public UserInfo() {

        FacesContext ctx = FacesContext.getCurrentInstance();
        ExternalContext ectx = ctx.getExternalContext();
 
        //Ask the container who the user logged in as
        _userName = ectx.getRemoteUser();
 
        //Default the value if not authenticated
        if (_userName == null || _userName.length()==0) {
            _userName = "Not Authenticated";
        }        //Set the user role flag...
        //Watch out for a tricky bug here:
        //We have to evaluate the roles Most > Least restrictive 
        //because the manager role is assigned to the technician and user roles 
        //thus checking if a manager is in "user" will succeed and we'll stop 
        //there at the lower level of priviledge
        for (int i=(ROLE_NAMES.length-1);i>0;i--)  {
            if (ectx.isUserInRole(ROLE_NAMES[i])){
                _userRole = i;
                break;
            }
        }
}    /**
     * @return the String role name
     */
    public String getUserRole() {
        return ROLE_NAMES[_userRole];
    }    /**
     * Get the security container user name of the current user.
     * As an additional precaution make it clear when we are running in
     * Dev mode.
     * @return users login name which in this case is also their email id.     */
    public String getUserName() {
      StringBuffer name = new StringBuffer(_userName);
      if (_devMode) {
        name.append(" (Development Mode)");
      }
      return name.toString();
    }    /**
     * Function designed to be used from Expression Language
     * for swiching UI Features based on role.
     * @return boolean
     */
    public boolean isCustomer() {
        return (_userRole==USER_ROLE);
    }    /**
     * Function designed to be used from Expression Language
     * for switching UI Features based on role.
     * @return boolean
     */
    public boolean isTechnician() {
        return (_userRole==TECHNICIAN_ROLE);
    }    /**
     * Function designed to be used from Expression Language
     * for switching UI Features based on role.
     * @return boolean
     */
    public boolean isManager() {
        return (_userRole==MANAGER_ROLE);
    }    /**
     * Function designed to be used from Expression Language
     * for switching UI Features based on role.
     * This particular function indicates if the user is either
     * a technician or manager
     * @return boolean
     */
    public boolean isStaff() {
        return (_userRole>USER_ROLE);
    }    /**
     * Function designed to be used from Expression Language
     * for switching UI Features based on role.
     * This particular function indicates if the session is actually authenticated
     * @return boolean
     */
    public boolean isAuthenticated() {
        return (_userRole>NOT_AUTHENTICATED);
    }
}

30.8.1.2 Creating a Managed Bean for the Security Information

The UserInfo bean is registered as a managed bean named userInfo in the JSF faces-config.xml file. The managed bean uses expressions for managed properties which the UserInfo.java class implements.

For example, in the SRDemo application the following expressions appear in the UserInfo managed bean:

  • #{userInfo.userName} either returns the login Id or the String "Not Authenticated"

  • #{userInfo.userRole} returns the current user's role in its String value, for example, manager

  • #{userInfo.staff} returns true if the user is a technician or manager

  • #{userInfo.customer} returns true if the user belongs to the role user

  • #{userInfo.manager} returns true if the user is a manager

To define the managed bean properties and expressions:

  1. In the Application Navigator, open the faces-config.xml file in the user interface WEB-INF folder.

  2. In the window, select the Overview tab.

  3. In the element list on the left, select Managed Beans and click New.

  4. In the Create Managed Bean dialog specify the class information for the managed bean. If you have not created the class, see Section 30.8.1.1, "Creating a Class to Manage Roles".

  5. To permit the security information defined by the managed bean to accessible by multiple web pages, set Scope to Session. For example, the SRDemo application defines the managed bean name userInfo, corresponding to the UserInfo.java class.

Example 30-8 shows the portion of the faces-config.xml file that defines the managed bean userInfo to hold security information for the SRDemo application.

Example 30-8 Managed Beans in the SRDemo faces-config.xml File

<!-- The managed bean used to hold security information -->
  <managed-bean>
    <managed-bean-name>userInfo</managed-bean-name>
    <managed-bean-class>oracle.srdemo.view.UserInfo</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>