Using database tables for authentication in ADF applications

This article describes how to make a login feature for your application, which uses database tables for authentication and authorization.

I have made this loginmodule from examples of the AMIS adf training and i have made use of the DBLoginModule class which Frank Nimphius and Duncan Mills build.

First thing we need to build is the tables in the database.

Tables

The loginmodule uses three tables.
1 table for users: which we call AMIS_STAFF
1 table for roles: which we call ROLES
1 table for association between the AMIS_STAFF and the ROLES tables
So make the tables in your database. The picture bellow shows how you could make it.

Using database tables for authentication in ADF applications tables

Authorization

Before we configure the authorization of your webapplication we need to make a new application.

So build a new application.
– Call the new application: SecureWebApp
– Directory name: c:\projects\SecureWebApp
– Application Package Prefix: nl.amis.als.secureWebApp
– Application Template: Web Application[JSF, ADF BC]
(these are just my settings, change them if you like)

– ok now we have an application
– make a new jsp page and call it: login.jsp
– save the page in …..\public_html\security\pages
– the source of the page look like this:

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>
<%@ page contentType=”text/html;charset=UTF-8″%>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″/>
<title>Login</title>
</head>
<body style=”font-family:sans-serif; background-color:rgb(214,231,255); color:rgb(0,0,255);”>

<form action=”j_security_check” method=”post”>
<table cellspacing=”3″ cellpadding=”2″ border=”0″ width=”100%”>
<tr>
<td width=”120″>
<b style=”whitespace:nowrap”>Username</b>
</td>
<td>
<input type=”text” name=”j_username”/>
</td>
</tr>
<tr>
<td width=”120″>
<b>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>
</table>
</form>

<p>
(c) AMIS – (2002-2006) – <a href=”http://www.amis.nl”>http://www.amis.nl</a>
</p>
</body>
</html>

Now we have a login page. The next thing is to make the correct settings to use the page, the proper constraints and the roles.

Roles

Select the web.xml of your project and click rightmousebutton, select properties.
Select the Security Roles, add several roles, for example MANAGER, USER.
An important note is that the entered roles in your security roles, has to be exact the same as in the ROLES table we’ve made in the database.

Constraints

Select the web.xml of your project and click rightmousebutton, select properties.
Select Security Contraints, make a new constraint.
Select the new made constraint and add an Url Pattern. An example: /faces/pages/*.
The constraint is made, now we need to add roles to the constraint.
Select the Auhtorization tab and select the roles which use the constraint.

Login configuration

Select the web.xml of your project and click rightmousebutton, select properties.
Select the Login Configuration: Form-Based Authentication
Enter the next settings:
Login page: /faces/security/pages/login.jsp
Error page: /faces/security/pages/login.jsp

Authentication

Install jar file
We need to download a loginmodule, which we add a java class.
The file is available at a blog about a login configuration with an pl/sql procedure: https://technology.amis.nl/blog/?p=1462 or direct from: https://technology.amis.nl/wp-content/uploads/images/JaasSecureWebApp.zip
The file we needed is: jaasdatabaseloginmodule.zip
Download the file
Unzip the file and run the project, the project should look like this:

Using database tables for authentication in ADF applications loginmodule without java class

Ok now we are making a new java class in: oracle.sample.dbloginmodule.DBTableLM
The name of the file is: ALSDBTableLoginModule
The result should look like this:
Using database tables for authentication in ADF applications loginmodule with java class

Now we open the DBTableLoginModule.java file and copy paste all code into: ALS DBTableLoginModule.
The code we just pasted into our new class will be adjusted to our preferences.
First the need to adjust the class name: public class DBTableLoginModule implements DBLoginModule into: public class ALSDBTableLoginModule implements DBLoginModule.
The file should be correct at this point (so no file errors should occur if you run the file).
The performDbAuthentication is the only thing we adjust in the java class, the code of the method is as follow:

protected boolean performDbAuthentication(String username, char[] password)
{
boolean success = false;
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
ArrayList _dbauth = new ArrayList();

String _sqlStatement = “select roles.ROLENAME, amis_staff.USERNAME FROM roles LEFT JOIN userrole ON roles.ID = userrole.ROLE LEFT JOIN amis_staff ON userrole.EMPLOYEE = amis_staff.ID WHERE amis_staff.USERNAME = ‘” + username + “‘ AND amis_staff.PASSWORD = ‘” + new String(password) + “‘”;

try
{
try
{
//database connection from the data-sources.xml file
Context ic;
try
{
ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup(_data_source_name);
conn = dataSource.getConnection();
}
catch (NamingException e)
{
System.err.println(e.getMessage());
}

stmt = conn.createStatement();
rset = stmt.executeQuery(_sqlStatement);

while (rset.next())
{
success = true;
String rolename = rset.getString(1);
String user = rset.getString(2);

_dbauth.add(new DBRolePrincipal(rolename));
_dbauth.add(new DBUserPrincipal(user));
_authPrincipals=(Principal[]) _dbauth.toArray(new Principal[_dbauth.size()]);

}

rset = stmt.executeQuery(_sqlStatement);
if(!rset.next())
{
FacesContext facesContext = FacesContext.getCurrentInstance();
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,”Your username and/or password is incorrect! “,null);
facesContext.addMessage(“messages”,message);
}
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
finally
{
rset.close();
stmt.close();
conn.close();
}
}
catch (SQLException e)
{
System.err.println(e.getMessage());
}
return success;
}

Compile the project
Select DBLoginModule.deploy, rightmousebutton and click deploy to JAR file.
The jar has to be used in the library of the project.
Copy the jar file to the jdev\lib map of your jdeveloper installation. For example: C:\Program Files\jdevstudiobase10133\jdev\lib.
The jar file is ready to use, only we have to make is available in the OC4J container.
So open the application.xml file, located in JDEV_HOME\jdev\system\oracle.j2ee.10.1.3.41.57 \embedded-oc4j\config map.
Replace: <jazn provider=”XML”/> by:

<jazn provider=”XML”>
<property name=”custom.loginmodule.provider” value=”true”/>
<property name=”role.mapping.dynamic” value=”true”/>
</jazn>

And add: <library path=”C:\Program Files\jdevstudiobase10133\jdev\lib\DBLoginModule.jar”/>

Configure system-jazn-data.xml

Let’s open the system-jazn-data.xml file in an editor. The file is located in the JDEV_HOME\jdev\system\oracle.j2ee.10.1.3.41.57 \embedded-oc4j\config map.
In the file we add the next lines:
<application>
<name>current-workspace-app</name>
<login-modules>
<login-module>
<class>oracle.sample.dbloginmodule.DBTableLM.ALSDBTableLoginModule</class>
<control-flag>required</control-flag>
<options>
<option>
<name>addAllRoles</name>
<value>true</value>
</option>
<option>
<name>debug</name>
<value>true</value>
</option>
<option>
<name>data_source_name</name>
<value>jdbc/OracleDSSecurity</value>
</option>
<option>
<name>log_level</name>
<value>ALL</value>
</option>
</options>
</login-module>
</login-modules>
</application>

These settings we use to make the ALSDBTableLoginModule class available to the application.

Configure data-source.xml

Let’s open the data-source.xml file in an editor. The file is located in the JDEV_HOME\jdev\system\oracle.j2ee.10.1.3.41.57 \embedded-oc4j\config map.
In the file we add the next lines:
<managed-data-source name=”OracleDSSecurity” connection-pool-name=”Security Pool” jndi-name=”jdbc/OracleDSSecurity”/>

<connection-pool name=”Security Pool”>
<connection-factory factory-class=”oracle.jdbc.pool.OracleDataSource” user=”als” password=”als” url=”jdbc:oracle:thin:@localhost:1521:xe”/>
</connection-pool>
User is the database user, and the password is the user’s password.
The url is the url of the database.
These settings we’ve made, are necessary to make a database connection.
We are now able to login.

16 Comments

  1. Shreyas February 20, 2012
  2. kunal September 2, 2011
  3. David Williams January 28, 2010
  4. Subrata Biswas December 28, 2009
  5. Subrata Biswas September 22, 2009
  6. Richard Hunt August 18, 2009
  7. jt June 17, 2009
  8. zhouxiao315@yahoo.com.cn October 30, 2008
  9. andrew October 25, 2008
  10. Lutchumaya September 30, 2008
  11. ab September 8, 2008
  12. Andy Dorfman May 12, 2008
  13. Andriejus Putiatinas March 25, 2008
  14. Johan Tuitel February 21, 2008
  15. Mike Lehmann February 14, 2008
  16. Herman Scheltinga February 11, 2008