Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3.0) Part Number B28967-02 |
|
|
View PDF |
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:
Section 18.1, "Introduction to Security in Oracle ADF Web Applications"
Section 18.3, "Configuring Authentication Within the web.xml File"
Section 18.6, "Implementing Authorization Using Oracle ADF Security"
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:
Authentication provides a way to determine who the current user is. Oracle ADF Security can authenticate users against data within various resource providers.
Authorization provides a way to restrict access to the application or parts of the application (called resources) based on the user attempting to access the resource. Oracle ADF Security allows you to set authorization on ADF Model layer objects.
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.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.
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" />
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.
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 18.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.
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 theweb.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:
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.
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.
Save all changes and proceed to create the login configuration, as described below.
Figure 18-1 shows the web.xml
editor with the Security Roles definition displayed. In the SRDemo application, three security roles are defined.
Before configuring the login configuration, you should already have created a login web page and the optional login error page. For details, see Section 18.4, "Creating a Login Page".
To create a login configuration for J2EE container-managed security:
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.
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 18.4.1, "Wiring the Login and Error Pages".
Save all changes and close the Web Application Deployment Descriptor editor.
Figure 18-2 shows the web.xml
editor with the Login Configuration definition displayed.
To create security constraints for J2EE container-managed security:
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.
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.
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.
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.
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.
To specify transport guarantee, select the User Data tab. Select the type of guarantee to use.
Save all changes and close the Web Application Deployment Descriptor editor.
Figure 18-3 shows the web.xml
editor with a Security Constraint definition displayed.
Example 18-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 18-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.
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 parametersuccess_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:
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.
Define Security Roles, Login Configuration, and Security Constraints as you normally would. (See above procedures.)
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.
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
Save all changes and close the Web Application Deployment Descriptor editor.
Figure 18-4 shows the web.xml
editor with the Servlet Mapping definition displayed for the adfAuthentication servlet.
Example 18-2 shows sample definitions similar to the ones that your web.xml
file should contain.
Example 18-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.
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 18-5 shows a 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:
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.
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.
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.
Click Finish to complete the wizard and add the JSPX file to the user interface project.
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.
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
.
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.
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.
Drag Text Field for the user name into the form and set the name to j_username
.
Drag Password Field into the form and name it j_password
.
Drag Submit Button into the form with label set to Sign On
.
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 18-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 18-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>&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>&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>&nbsp;</td> <tr> <td>&nbsp;</td> </tr> <tr> <td>&nbsp;</td> </tr> <tr> <td colspan="3"> <hr/> </td> </tr> </table> </form> </c:if> </body> </html>
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:
In the Application Navigator, locate web.xml in the WEB-INF folder.
Right-click web.xml and choose Properties.
In the Web Application Deployment Descriptor dialog, select Login Configuration.
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 18-6 shows the web.xml
editor with the Login Configuration definition displayed.
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 18-3 shows the conventions of that permit the HTML Form to invoke the authentication servlet. Specifically, the form must specify three pieces of information:
<form action="j_security_check" method="post">
to invoke the security check method j_security_check
on the container's login bean.
<input type="text" name="j_username"/>
to assign the username value to the container's login bean attribute j_username
.
<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.
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 18-7 shows the logout page from the SRDemo application.
To create the logout page:
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.
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.
On the Component Binding page, do not create a managed bean.
On the Tag Libraries page of the wizard, add ADF Faces Components and ADF Faces HTML to the Selected Libraries list.
Click Finish to complete the wizard and add the JSPX file to the user interface project.
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.
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.
To create the buttons that give the user the choice whether to logout or not, drag two CommandButton components inside the PanelButtonBar.
The first button should provide the logout function. You can wire it separately by creating a managed bean. For details, see Section 18.5.1, "Wiring the Logout Action".
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 18-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 18-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>
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:
In the open logout page, double-click the command button that you reserved for the logout action.
In the Action property dialog, leave Method Binding selected and click New to define the Managed Bean class.
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.
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 18-8 shows the Action property dialog with the managed bean backing_SRLogout
and the method logoutButton_action()
entered.
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 18-5 for a sample.
Warning:
If your application calls theinvalidate()
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 18-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 18-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; }
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 18-5, invalidates the session and redirects to the home page.
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 18.7, "Implementing Authorization Programmatically".The following Oracle ADF objects are security-aware as defined by the page definition file associated with each databound web page:
Binding container
Iterator binding
Attribute binding
MethodAction binding
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 18-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 18-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:
Configure authentication for the ADF Authentication servlet. For details, see Section 18.3.3, "How to Enable Oracle ADF Authentication".
Configure your application to use Oracle ADF Security authorization. For details, see Section 18.6.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.
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:
Right-click on the project for which security is needed and choose New.
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.
In the Items list, select XML Document and click OK.
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.
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>
Save and close the file.
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 theauthorizationEnforce
parameter to false.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 }
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 18-1 for details about available Oracle ADF permissions.
To grant permissions on the binding container using the Authorization Editor:
Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.
In the Structure window, right-click the root node, PageDef, and choose Edit Authorization.
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.
You use the Authorization Editor to grant permissions for users on iterator bindings. See Table 18-1 for details about available Oracle ADF permissions.
To grant permissions on iterators using the Authorization Editor:
Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.
In the Structure window, expand the executables node.
Right-click on the iterator you wish to grant a permission for and choose Edit Authorization.
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.
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 18-1 for details about Oracle ADF permissions.
To grant permissions on attribute and method bindings using the Authorization Editor:
Create your web page. From the Visual Editor, right-click the page and choose Go to Page Definition.
In the Structure window, expand the bindings node.
Right-click on the attribute or method action binding you wish to grant a permission for and choose Edit Authorization.
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.
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 18-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 MethodPermission
to invoke the deleteDepartments()
method, and also an AttributePermission
to read the DepartmentID
attribute value.
Example 18-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.MethodPermission</class> <name>SessionEJB.dataProvider.deleteDepartments</name> <actions>invoke</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.
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 through the userid
property) 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 18.3.1, "How to Enable J2EE Container-Managed Authentication".
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 10.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']}"
action="#{backing_SRList.editButton_action}"
rendered="#{userInfo.manager}"/>
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>
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:
In the New Gallery select the General category and the Java Class item.
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 18-7 shows the key methods that the SRDemo application implements:
Example 18-7 SRDemo Application UserInfo.java Sample
/** * Constructor */ public UserInfo() { FacesContext ctx = FacesContext.getCurrentInstance(); ExternalContext ectx = ctx.getExternalContext(); //Only allow Development mode functions if security is not active _devMode = (ectx.getAuthType() == null); //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; } } } /* * Function to take the login name from the container and match that * against the email id in the USERs table. * Note this is NOT an authentication step, the user is already * authenticated at this stage by container security. The binding * container is injected from faces-config.xml and refers to a special * pageDef "headless_UserInfoPageDef.xml" which only contains the definition * of this method call, */ private Integer lookupUserId(String userName) { if (getBindings() != null) { OperationBinding oper = (OperationBinding)getBindings().getOperationBinding("findUserByEmail"); //now set the argument to the function with the username we want Map params = oper.getParamsMap(); params.put("emailParam",userName); // And execute User user = (User)oper.execute(); setUserobject(user); //It is possible that the data in the database has changed and //there is no match in the table for this ID - return an appropriate //Error in that case if (user != null){ return user.getUserId(); } else{ FacesContext ctx = FacesContext.getCurrentInstance(); ctx.addMessage(null,JSFUtils.getMessageFromBundle ("srdemo.dataError.userEmailMatch",FacesMessage.SEVERITY_FATAL)); return -1; } } else { //This can happen if the ADF filter is missing from the web.xml FacesContext ctx = FacesContext.getCurrentInstance(); ctx.addMessage(null,JSFUtils.getMessageFromBundle ("srdemo.setupError.missingFilter",FacesMessage.SEVERITY_FATAL)); return -1; } } /** * @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); } }
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:
In the Application Navigator, open the faces-config.xml
file in the user interface WEB-INF folder.
In the window, select the Overview tab.
In the element list on the left, select Managed Beans and click New.
In the Create Managed Bean dialog specify the class information for the managed bean. If you have not created the class, see Section 18.7.1.1, "Creating a Class to Manage Roles".
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.
In the Overview window, click the arrow to the left of the Managed Properties bar (appears below the managed bean list) to display properties of the bean.
Click New to create a unique managed bean property bindings with the value #{data.<
ManagedBeanName+PageDefID
}
. In the Oracle ADF model, the variable bindings makes the binding objects accessible to EL expressions. In the SRDemo application defines the bindings property as UserInfoPageDef. The importance of this expression is described in Section 18.7.2.3, "Create a Page Definition to Make the Method an EL Accessible Object".
Optionally, click New to create the security properties that your application will access. For example, the SRDemo application defines the userName and userRole properties as Strings. Figure 18-9 shows the managed bean overview created for the SRDemo application.
Example 18-8 shows the portion of the faces-config.xml
file that defines the managed bean userInfo
to hold security information for the SRDemo application. Note that the managed bean also defines the managed property bindings
. Note that the values shown for managed property userName
and userRole
are ignored by the SRDemo application and were included for test purposes only.
Example 18-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-property> <property-name>bindings</property-name> <value>#{data.UserInfoPageDef}</value> </managed-property> <!-- Test Data ignored if real security is in use--> <managed-property> <property-name>userName</property-name> <property-class>java.lang.String</property-class> <value>sking</value> </managed-property> <managed-property> <property-name>userRole</property-name> <property-class>java.lang.String</property-class> <value>manager</value> </managed-property> <!-- End Test Data --> </managed-bean>
The managed bean does have some interaction with the Oracle ADF Model layer. Once the user logs in and the logon ID is obtained, the application needs to translate the login ID into the unique userid that permits the application to identify the user. This information can then be used throughout the application to determine what menus and functionality to display. For instance, in the SRDemo application, the SRList page will only display the Edit button when the user logged in belongs to the manager role. The same authorization restraints is applied to the SRCreate page.
To obtain a unique userid that databound web pages can use to perform authorization:
Create a TopLink named query that will return a user object for a particular id (which is the value obtained from the container security).
Create a method on the session bean facade that wraps this lookup method up.
Create an ADF page definition file for the managed bean to describe its use of this lookup method on the session bean.
Inject the binding information into the UserInfo bean to provide access to the ADF Model layer to invoke the method on the session bean.
Execute the custom method from the UserInfo bean the first time the particular id is required for authorization.
You can identify the user who logs into the application through a named query. This query will return a user object for a unique identifier, such as a particular email id, received from the container security. The query is read-only and takes a String parameter containing the identifier.
To create a named query, use the descriptor of the TopLink SRMap file that corresponds to the USERS table. The query in SRDemo application is based on the email id and receives its value from the security container.
For more information about TopLink named queries, see Section 3.8, "Creating and Modifying Objects with a Unit of Work".
To create a named query for the User entity:
In the Application Navigator, expand the data model project and open SRMap to display the Mapping editor.
In the Structure window, expand the entities package.
In the Mapping editor, select the descriptor User and click Add to define a new TopLink named query. For example, SRDemo application uses findUserByEmail
.
Use the General panel to add a parameter that identifies the unique attribute. For example, the SRDemo application uses emailParam
of type java.lang.String
.
Use the Format panel to define an expression for the named query. For example, the SRDemo application uses email EQUAL emailParam
.
Save the query.
Oracle recommends that you use a session facade to access entities and methods in order to expose services to clients. The session bean that implements the session facade design pattern, becomes your application's entry point for the Oracle ADF data control. Chapter three describes how to expose services with ADF data controls. Like other methods to be invoked at application runtime, the finder method for the named query must be registered with the Oracle ADF EJB data control in your project. This step begins the process of allowing the ADF Model layer to access the user security information for a uniquely identified user.
If you have not already created a session facade to wrap the TopLink queries, see Section 3, "Building and Using Application Services".
To add a finder method to an existing the session facade:
Expand the data model package that contains the session bean for which you created the ADF EJB data control.
Double-click the session bean .java
file to open it in the source editor.
Add the new method. Example 18-9 shows the session facade finder method implemented in the SRDemo application.
In the Application Navigator, right-click the session bean and choose Edit Session Facade.
In the Application Navigator, add the new method to the remote interface.
Save the .java
file and recompile.
In the Application Navigator, right-click the session bean and choose Create Data Control. The new method will appear on the Data Control Palette.
Example 18-9 SRDemo SRPublicFacadeBean.java Finder Method to Expose Unique ID
public User findUserByEmail(String emailParam) { Session session = getSessionFactory().acquireSession(); Vector params = new Vector(1); params.add(emailParam); User result = (User)session.executeQuery("findUserByEmail", User.class, params); session.release(); return result; }
After the finder method used to return a unique id for the user has been registered with the ADF data control, the next step in exposing the finder methods to the Oracle ADF Model layer is to provide a page definition description, where it will be defined as a method action binding. Once the binding is exposed by the Oracle ADF Model, it can be used throughout the application pages.
Typically, each web page maps to a single page definition file. However, when the action binding is to be accessible throughout the application, the binding definition must belong to its own page definition—one that is "headless"—without a corresponding web page.
To create a headless page definition file for the user interface project:
In the Application Navigator, expand the user interface package that contains the page definition files.
Right-click the pageDefs package node and choose New.
In the New Gallery, create an XML document from the General - XML category.
In the Create XML File dialog, name the file for the managed bean that defines the security properties and append PageDef
. For example, in the SRDemo application, the headless page definition is named headless_UserInfoPageDef.xml
.
Open the XML file in the source editor and add the method binding definition. Example 18-10 shows the binding definition created for the SRDemo application.
Save the file.
The value 999
(or CUSTOM
) set on the action property of the methodBinding specifies the method to be invoked is a custom method defined by the application service.
Example 18-10 SRDemo headless_UserInfoPageDef.xml Page Definition File
<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
version="10.1.3.35.65" id="UserInfoPageDef"
Package="oracle.srdemo.view.pageDefs">
<bindings>
<methodAction id="findUserByEmail"
InstanceName="SRPublicFacade.dataProvider"
DataControl="SRPublicFacade"
MethodName="findUserByEmail" RequiresUpdateModel="true"
Action="999"
ReturnName="SRPublicFacade.methodResults.
SRPublicFacade_dataProvider_findUserByEmail_result">
<NamedData NDName="emailParam" NDType="java.lang.String"/>
</methodAction>
</bindings>
</pageDefinition>
The ADF Model layer loads the page definition from the path reference that appears in the DataBinding.cpx
file. The new page definition file needs to have this reference to id "UserInfoPageDef
" within DataBindings.cpx
. This can be done from the Structure window for the CPX file.
To create a headless page definition file for the user interface project:
In the Application Navigator, expand the root user interface package and locate the DataBindings.cpx
file. The packages appear in the Application Sources folder.
Double-click DataBindings.cpx and open the Structure window.
In the Structure window, select the pageDefinitionUsages node and choose Insert Inside pageDefinitionUsages > page.
Set Id to the name you specified for your headless page definition file (contains the single methodAction binding). For example, the SRDemo application uses UserInfoPageDef
.
Set path to package that where you added the page definition file. For example, in the SRDemo application, the path is oracle.srdemo.view.pageDefs.userInfo
.
At runtime, a reference to data.
<Headless_PageDefID>
will now resolve to this binding definition. Example 18-11 shows the id specified for the headless page definition file in the SRDemo application.
Example 18-11 SRDemo DataBindings.cpx Page Definition Reference
<?xml version="1.0" encoding="UTF-8" ?> <Application xmlns="http://xmlns.oracle.com/adfm/application" ... <pageDefinitionUsages> <page id="SRListPageDef" path="oracle.srdemo.view.pageDefs.app_SRListPageDef"/> <page id="UserInfoPageDef" path="oracle.srdemo.view.pageDefs.headless_UserInfoPageDef"/> ... </Application>
In the managed bean definition userInfo
, you may have already defined a managed property bindings
that has the value #{data.UserInfoPageDef}
. For details, see Section 18.7.1.2, "Creating a Managed Bean for the Security Information".
To compliment the expression, the class that implements the security methods (UseInfo.java
) requires a corresponding getter and setter method for the bindings
property:
public void setBindings(BindingContainer bindings) { this._bindings = bindings; } public BindingContainer getBindings() { return _bindings; }
The first time the application requires the UserId
, the session bean method is called. This is done using the getUserId()
method in UserInfo.java
. The getUserId()
method checks to see if the UserId
is currently populated. If not, it makes a call to a private method lookupUserId()
that actually calls the session facade method:
public Integer getUserId() { if (_userId == null){ _userId = lookupUserId(_userName); } return _userId; }
The lookupUserId()
method is responsible for invoking the methodAction binding which calls the session facade method defined to get the user ID:
private Integer lookupUserId(String userName) { if (getBindings() != null) { OperationBinding oper = (OperationBinding)getBindings(). getOperationBinding("findUserByEmail"); //now set the argument to the function with the username we //are interested in Map params = oper.getParamsMap(); params.put("emailParam",userName); // And execute User user = (User)oper.execute(); setUserobject(user); return user.getUserId(); } }
The method uses getBindings()
to get the injected binding container from the Faces configuration. Once the binding container is obtained, the method looks up the methodAction binding responsible for coordinating with the session facade method. For details about the session facade method, see Section 18.7.2.4, "Executing the Session Facade Method from the UserInfo Bean".