Customizing Content With
Oracle XML DB and J2EE features
Security Implementation
December 2002
|
|
The XMLNews application has adopted Form-based-authorization to
customize the user authentication interface. In form-based
authentication, you can customize the login screen and error pages
that are presented to the end user by an HTTP browser. Also, the
content of the user dialog box is sent as plain text, and the target
server is not authenticated.
In XMLNews application, authentication is only for the UI (JSPs)
i.e Views layer and not for the underlying EJBs. From the security
perspective, there are two types of web pages in the application;
authenticated and non-authenticated pages. To access the authenticated
pages, end-users have to be authenticated. In the current sample
application, user validation for username/password is done against
Oracle database table using custom UserManager class. Apart from
the username/password validation, role validation is also done.
With this, the application is implemented in such a way that content
of the authenticated page will also depend on the role of the user.
Following are the implementation details:
Custom User Interface
Custom login page is defined in web.xml
file which is read by OC4J at the application start up. Here is
how web.xml entries look for the XMLNews application. This
configuration defines the custom
loginMain.jsp that is used in the
application for login interface. Also, errorLogin.jsp when
the login fails.
............ <login-config> <auth-method>FORM</auth-method> <realm-name>Form-Based Authentication for XML NEWS</realm-name> <form-login-config> <form-login-page>user/loginMain.jsp</form-login-page> <form-error-page>user/errorLogin.jsp</form-error-page> </form-login-config> </login-config> .................
|
Defining URLs to be authenticated
All the pages to be authenticated will have
a defined URL pattern. In the XMLNews sample, all the pages having
pattern starting with 'auth' will need to be authenticated
before viewing the page. The URL pattern is defined in web.xml.
Note the role definitions also.
............ <security-constraint> <web-resource-collection> <web-resource-name>xmlnews</web-resource-name> <url-pattern>/xmlnews/auth*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>admins</role-name> <role-name>users</role-name> <role-name>manager</role-name> <role-name>newsprovider</role-name> <role-name>enduser</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint>
</security-constraint>
.................
|
Using custom UserManager Class
OC4J has support for pluggable UserManagers.
The class: MyUserManager.java under oracle.otnsample.eis
layer implements the com.evermind.security.UserManager interface.
The UserManager is responsible for locating, creating, editing,
removing and managing Group object. User management is done in the
database. The custom UserManager class will validate the username/password
and associated role of the user to allow access to the authenticated
pages. OC4J will make use of the custom UserManager class when
orion-application.xml has valid entries defining user manager
class.
<?xml version="1.0"?> <!DOCTYPE orion-application PUBLIC "-//Evermind//DTD J2EE Application runtime 1.2//EN" "http://xmlns.oracle.com/ias/dtds/orion-application.dtd">
<orion-application deployment-version="9.0.2.0.0" default-data-source="jdbc/OracleDS"> <data-sources path="./data-sources.xml" /> <principals path="./principals.xml" /> <user-manager class="oracle.otnsamples.eis.MyUserManager"> </user-manager>
.................
|
MyUserManager.java
extends from SimpleUserManager.java and has implemented
following 3 methods:
protected boolean userExists( String username
);
protected boolean checkPassword( String username, String password
);
protected boolean inGroup( String username, String groupname );
The password checking and inGroup validation is done using XMLNEWS
schema table 'USERS' in Oracle Database.
Here is the code snippet for 'checkPassword' method in MyUserManager.java
......... protected boolean checkPassword(String username, String password) {
// Rowset to get results of the query to find password of the user. RowSet rSet; String pword = null;
// create arraylist to store parameters to be sent to the query. ArrayList params = new ArrayList(); params.add(username);
// set the default flag status to false. boolean flag = false; try {
// Get an instance of DBBroker class and Execute the SQL Statement
// The sql queries the password for the given username rSet = DBBroker.getDBBroker("xmlnewsDB").execute("SELECT password FROM users WHERE user_name =? ", params);
// get password from rowset while(rSet.next()) { pword = rSet.getString(1); }
// if password is correct then, flag true. if(password.equals(pword)) { flag = true; } } catch(Exception Ex) {
} return flag; // return flag } ............
|
All the application users will fall under
different groups. This is defined in principals.xml file
which is read by OC4J at the application startup. Here is the
listing of principals.xml file which has defined five groups
for the application which will find corresponding mapping to the
role in the USERS table in the database.
<?xml version="1.0" standalone='yes'?> <!DOCTYPE principals PUBLIC "//Evermind - Orion Principals//" "http://xmlns.oracle.com/ias/dtds/principals.dtd">
<principals> <groups> <group name="users" /> <group name="admins" /> <group name="manager" /> <group name="newsprovider" /> <group name="enduser" /> </groups>
<users></users> </principals>
|
Below is the code snippet for 'inGroup' method
in MyUserManager.java which checks the role of the user from database,
matches the role and group defined in principals.xml file. So,
the role obtained and validated thus is made use of while displaying the
content of the views i.e JSPs in the application.
.................. protected boolean inGroup(String username, String groupname) {
// rowset to hold resultsof the query RowSet rSet; String uRole = null;
// array list to pass values for the bind parameters to the query. ArrayList params = new ArrayList(); params.add(username); // add username try {
// Get an instance of DBBroker class and Execute the SQL Statement // The sql queries the role for the given user. rSet = DBBroker.getDBBroker("xmlnewsDB").execute("SELECT lower(role) FROM users WHERE user_name =? ", params);
// get the role of the user from rowset. if(rSet.next()) { uRole = rSet.getString(1); } } catch(Exception Ex) {
}
// return true when the role maps correctly to the groupname identified // in the application defined in principals.xml return uRole.equals(groupname); } ...........
|
|