Feature
Implementing J2EE Form-Based Authentication
Digg This!
The J2EE security model provides a built-in security concept based on roles provided by deployment descriptors. The deployment descriptors contain elements that allow us to map users or groups of users to specific roles (this information is used to authenticate the user) - and to specify which roles are allowed access to which resources. All users mapped to a particular role are allowed access to a certain resource. (This information is used to determine if the user is authorized to access the resource or not.)
For purposes of discussion, let us consider a simple J2EE application that has a few Web pages and one Enterprise JavaBean (EJB), which is a simple session bean. The J2EE containers that house these two different types of J2EE application components are:
1. Web container: Houses static HTML pages, servlets, JavaServer Pages, image files such as GIFs, etc.; its deployment descriptor is web.xml.
2. EJB container: Houses EJB components; its deployment descriptor is ejb-jar.xml.
Web Container Authentication Mechanisms
Since this J2EE application has a Web component, it makes sense to authenticate users from a Web page. The Web container provides the following authentication mechanisms that can be applied to this situation:
1. Basic: In this mechanism, when the user attempts to access a protected resource, the Web container checks whether the user has been authenticated. If not, the browser's built-in login screen pops up to prompt the user to enter the username and password for the Web container to perform authentication
2. Form-based: In this mechanism, when the user attempts to access a protected resource, the Web container checks whether the user has been authenticated. If not, an application-specific login screen is displayed that prompts the user to enter the username and password for the Web container to perform authentication.
3. HTTPS: This mechanism uses HTTP over Secure Sockets Layer (SSL).
4. Hybrid: In basic and form-based authentication, passwords are not protected adequately. A hybrid mechanism overcomes this by running basic and form-based mechanisms over SSL.
From the above list of available mechanisms we are interested solely in the form-based authentication mechanism, since this best fits our requirement for an application-specific login screen to perform authentication.
User Registry
Having decided on the authentication mechanism, we need to determine where the user information is stored. We could use databases, Lightweight Directory Access Protocol (LDAP), or even the operating system to store user information. In this case, we'll use a relational database to store the user information. Since there is no industry-wide standard on the exact database schema of a custom user registry, WebSphere seeks to circumvent this problem by providing an interface
(com.ibm.websphere.security.CustomRegistry) that can be implemented.
This article seeks to provide a step-by-step guide to implementing form-based authentication for a simple J2EE application using a custom user registry in WebSphere Studio Application Developer v5.
Writing the Simple J2EE Application
Prerequisites
Start WebSphere Studio:
1. Go to the Windows Start menu.
2. Select Programs -> IBM WebSphere Studio -> Application Developer 5.0.
About the Application
We are about to create a simple J2EE application that manages the inventory for a retail store. Here we have two primary roles:
1. Manager: Denotes the role of the inventory manager. A user assigned to this role is allowed to order and view inventory.
2. Clerk: Denotes the role of inventory clerk. A user assigned to this role is allowed to view only inventory.
In order to illustrate these levels of security, we will implement the following:
1. For the Web component, we will create two files, order.html and view.html. In the Web deployment descriptor we will allow the "Manager" to access both files. However, we will allow the "Clerk" access to only view.html.
2. For the EJB component, we will create a session bean having two business methods, getOrder() and getView(). In the EJB deployment descriptor we will allow the "Manager" access to both of these business methods, but allow the "Clerk" access to only the getView() business method.
Custom User Registry Database
For implementing the custom user registry interface provided by WebSphere the database tables should follow a certain structure. The database scripts for Oracle
are available in Listing 1. (All of the code listings for this article can be downloaded from www.sys-con.com/websphere/sourcec.cfm.) The CustomUserRegistry class described later in this article will access user information in these tables via JDBC to authenticate users.
Creating the Sample J2EE Application
Create a new J2EE 1.3 enterprise application project in the WebSphere Studio Workbench called FormAuthExample and click Finish (see Figure 1). Then perform the following steps:
1. Right-click on FormAuthExampleWeb project.
2. Select Properties.
3. Click on Java Build Path.
4. From the Java Build Path option, click on the Projects tab. Check the box next to FormAuthExampleEJB project.
5. From the Java Build Path option, click on the Libraries tab. Click
on the "Add External JARs" button.
6. Browse and select the following file : C:\Program Files\IBM\WebSphere Studio\wstools\eclipse\plugins\com.ibm.websphere.aes.v4_4.0.4\lib\websphere.jar.
7. Click OK.
Configuring the Web Application
In the Web Perspective (FormAuthExampleWeb project), create the login.html page:
1. Right-click on /Web Content.
2. Select New->HTML File.
3. Enter login.html in the Name field.
4. Click Finish.
5. Modify the login.html file with the code in Listing 2.
Next, create the index.html page:
1. Right-click on /Web Content.
2. Select New->HTML File.
3. Enter index.html in the Name field.
4. Click Finish.
5. Modify the index.html file with the code in Listing 3.
Then create the error.jsp page:
1. Right-click on /Web Content.
2. Select New->JSP File.
3. Enter error.jsp in the Name field.
4. Click Finish.
5. Modify the error.jsp file with the following code:
Error Page
Error Page
Next, create the result.jsp page:
1. Right-click on /Web Content.
2. Select New->JSP File.
3. Enter result.jsp in the Name field.
4. Click Finish.
5. Modify the BODY section of the result.jsp file with the following code:
<%
String result = (String) session.getAttribute("result");
if(result == null)
{
result = "Sorry, you do not have the necessary privileges to execute
this business method !";
}
%>
<%=result%>
Next, create a new folder in the Web Content directory named "secure":
1. Right-click on /Web Content.
2. Select New->Folder.
3. Enter "secure" in the Folder Name field.
4. Click Finish.
Within the "secure" folder, create the order.html page:
1. Right-click on /Web Content/secure.
2. Select New->HTML File.
3. Enter order.html in the Name field.
4. Click Finish.
5. Modify the BODY section of the order.html file with the following code:
Order Inventory
Within the "secure" folder, create the view.html page:
1. Right-click on /Web Content/ secure.
2. Select New->HTML File.
3. Enter view.html in the Name field.
4. Click Finish.
5. Modify the BODY section of the view.html file with the following code:
View Inventory
Next, create a new package named "com.form.auth.example".
1. Right-click on /Java Source.
2. Select New->Package.
3. Enter com.form.auth.example in the Name field.
4. Click Finish.
Within the com.form.auth.example package, create the FormAuthServlet.java class.
1. Right-click on /Java Source/com.form.auth.example.
2. Select New->Class.
3. Enter FormAuthServlet in the Name field.
4. Click Finish.
5. Modify FormAuthServlet.java with the code in Listing 4.
Within the same package, create the CustomUserRegistry.java class.
1. Right-click on /Java Source/com.form.auth.example.
2. Select New->Class.
3. Enter CustomUserRegistry in the Name field.
4. Click Finish.
5. Modify CustomUserRegistry.java with the code shown in Listing 5.
Next, open the Web deployment descriptor, web.xml, located in
/Web content/WEB-INF directory, and do the following:
1. Click on the Servlets tab. Add FormAuthServlet and its URL mapping (alias).
2. Click on the Security tab.
3. In the Security Roles section, add two roles, Manager and Clerk. Note: Role names are case sensitive. Also you must ensure that these role names are the same as those specified in the database table, GROUPS.
4. In the Security Constraints section (of the same tab), add the following security constraints:
/secure/order.html is accessible by the Manager role only
/secure/view.html is accessible by roles - Manager and Clerk
/FormAuthServlet is accessible by roles - Manager and Clerk
5. Click on the Pages tab of the deployment descriptor. Select FORM as the authentication mechanism and enter FormAuthRealm as the Realm name, /login.html as the Login page, and /error.jsp as the Error page.
The source code for web.xml is shown in Listing 6.
Configuring the EJB Application
From the J2EE Perspective, create a new package, com.form.auth.example.ejb, in the ejbModule folder of the FormAuthExampleEJB project.
1. From the J2EE Navigator, right-click on /ejbModule/com.form.auth. example.ejb.
2. Select New->Enterprise Bean. (EJB Type must be Session Bean.)
3. Enter FormAuthExampleEJB in the Bean Name field.
4. Click Finish.
Next, open FormAuthExampleEJBBean.java and add the following code:
public String getOrder() {
return "Order Inventory";
}
public String getView() {
return "View Inventory";
}
Promote these two business methods to the EJB's remote interface. After this, the FormAuthExampleEJB.java file should have the following signatures added to it:
public String getOrder() throws java.rmi.RemoteException;
public String getView() throws java.rmi.RemoteException;
Save and generate deployed code for the session EJB component.
Next, open the EJB deployment descriptor, ejb-jar.xml, which is located in the FormAuthExampleEJB/ejbModule/META-INF folder.
1. Click on the Assembly Descriptor tab.
2. Under Security Roles, add the two roles, Manager and Clerk.
3. Under Method Permissions, set the following permissions. The getOrder() method will be accessible only to the Manager role. The getView() method will be accessible to both Manager and Clerk.
4. Under Container Transactions, set the transaction type to Required for all the methods of the FormAuthExampleEJB bean.
5. Next, click on the References tab of the deployment descriptor.
6. Add a remote reference to FormAuthExampleEJB.
7. Add the security role references for Manager and Clerk. Save the EJB deployment descriptor and generate deployed code.
Next, open the EAR deployment descriptor or application.xml located in the FormAuthExample/META-INF folder.
1. Click on the Security tab.
2. Click on Gather, which "gets" all the roles. This will be evident because the two created roles will appear in the list box on this tab.
3. For each role, check the Users/Groups check box and enter the corresponding role's name as group name under the Groups list.
The source code for ejb-jar.xml is shown in Listing 7.
Configuring the WebSphere Studio Server Environment
1. Create a new server project named FormAuthExampleServer.
2. Within this project, create a new server and server configuration named FormAuthExampleServer for the test environment.
3. Add the FormAuthExample EAR to the FormAuthExampleServer configuration.
4. Double-click on the FormAuthExampleServer server configuration.
5. In the server configuration, click on the Configuration tab. Check the Enable administrative console check box. Click on the Paths tab and add the following paths under ws.ext.dirs:
C:\Program Files\IBM\WebSphere Studio\workspace\FormAuthExampleWeb
\Web Content\WEB-INF\classes
C:\Program Files\IBM\WebSphere Studio\workspace\FormAuthExampleEJB
\ejbModule
6. Under Classpath, add:
C:\oracle\ora81\jdbc\lib\classes12.zip
7. Click on the Environment tab. Under system properties, add the following:
driver = oracle.jdbc.pool.OracleConnectionPoolDataSource
url = jdbc:oracle:thin:@servername:1521:ORCL
user = sample (Name of the schema)
password = ****** (DB
password)
These system properties are used by the com.form.auth.example.CustomUserRegistry
class
8. In the Security tab, check the Enforce Java 2 Security check box. Note: There are other settings in this tab that will need to be set after you complete the next section. Save the configuration.
Configuring the WebSphere Studio Admin Console
1. Start the FormAuthExampleServer server.
2. Once the server is started successfully, right-click on the server and select - Run administrative console. Note: Global Security must be disabled in order to run the administrative console. Therefore the Enable security check box in the Security tab of the server configuration must remain unchecked.
3. Type in any user ID and log in to the admin console. This user ID is used only for logging purposes.
4. Once logged in, using the left navigation tree of the admin console, click on Security->User Registries->Custom.
5. Specify the Server User ID as "geethar".
6. Specify the Server password as "pwd". (The user ID and password were inserted into the database tables as shown in Listing 1, which contains scripts to insert sample data after the tables are created.)
7. Specify the Custom registry class name as com.form.auth.example.CustomUserRegistry.
8. Click on the Custom Properties link on the same screen and enter the following values:
driver = oracle.jdbc.pool.OracleConnectionPoolDataSource
url = jdbc:oracle:thin:@servername:1521:ORCL
user = sample (Name of the schema)
password = ****** (DB
password)
9. Save the configuration
10. Next, using the left navigation tree of the admin console, click on Security->Global Security.
11. Check the Enable security check box.
12. Check the Enable Java 2 security check box.
13. Select Custom as the Active User Registry
14. Save the configuration.
15. Next, using the left navigation tree of the admin console, click on Security->JAAS->J2C Security.
16. Add a new entry whose:
Alias = ORCL
User ID = sample
Password = ****** (DB Password)
17. Save the master configuration.
Ensure that the module dependencies are specified correctly in the Properties->Project References for each project. For the FormAuthExampleWeb project, the projects FormAuthExample and FormAuthExampleEJB must be checked. For the FormAuthExample project, the projects FormAuthExampleWeb and FormAuthExampleEJB must be checked. For the FormAuthExampleEJB project, the project FormAuthExample must be checked.
Rebuild all three projects and publish to FormAuthExampleServer.
Restart the server. Test the application by running index.html on the server. When the user logs in as a Clerk, he or she can access only the View Inventory links, whereas when logging in as a Manager, the user can access all four links displayed on this page.
Conclusion
In this article, I have tried to demonstrate in a step-by-step manner how to implement form-based authentication using a custom user registry in WebSphere Studio Application Developer v5. This form of declarative security - being more flexible - is
preferred over programming or encoding security directly into applications. However, in cases where a more fine-grained level of security is required, some programmatic security will need to be implemented in conjunction with declarative security to achieve the
desired level of security.
Resources
Heijmans, M. (2003). "An LTPA Custom User Registry."
WebSphere Developer's Journal. SYS-CON Media. Vol. 2, issue 2.
Subrahmanyam. (2000). "Java Servlets Advanced Features." Java
Developer's Journal. Vol. 5, issue 2.
Mahapatra, S. (2001). "J2EE Application Security Model."
Java Developer's Journal. Vol. 6, issue 8.
About Geetha RamaswamyGeetha Ramaswamy is a technical architect at SBC Communications Inc. She holds a master's degree in computer science and has five years of experience working with Java and Web
technologies.