JDBCRealm in GlassFish

JDBC realm has a lot of attention in recent months. This blog summarizes the evolution of the JDBC realm implementation in GlassFish and explains how the latest implementation works. I would like to thank Jean-Baptiste, and Richter for their contributions and comments. The participation from the open source community definitely helps everyone. I encourage all of you to give feedback, participate, and help evolve this feature further.

GlassFish always had the capability for anyone to plug-in a realm. Implementing a custom realm in the Sun Java System Application Server EE 8.0 is described in the article Authentication Using Custom Realms in Sun Java System Application Server. In S1AS 7.x, there is a JDBC Realm bundled in sample. Jean-Baptiste formally filed an enhancement and provided a clear text version of JDBCRealm for GlassFish. Richter wrote another implementation because the GlassFish JDBCRealm at that time not compatible with Tomcat.

The latest GlassFish implemtation started with the Jean-Baptiste's implementation and includes the following modifications:

  • add message digest configuration
  • add encoding configuration for digest
  • add charset configuration
  • add database user and password configuration in realm
  • fix the issue with acquiring a connection for EJB

For the GlassFish implementation of the JDBCRealm, the following design descisions were made:

  • Should clear text passwords be supported? The decision was made to not to have clear text passwords as default storage mechanism. Under normal circumstances, passwords should not be stored as clear text.
  • Should this implementation be compatible with Tomcat and JBoss? The decision was made to attempt to implement this compatibility, but not require this compatibility.

I would appreciate hearing from you on both of these topics.

GlassFish JDBCRealm

The following table summarizes configurable properties for GlassFish JDBCRealm:

PropertiesMandatoryDefaultRemark
datasource-jndiY  
user-tableY  
user-name-columnY as in Tomcat, we assume that both user-table and group-table has this column
password-columnY  
group-tableY  
group-name-columnY  
jaas-contextY jdbcRealm
db-userNfrom connection pool configurationIf the connection pool doesn't have username or password, define the db-user and db-password here. This allows us to specify a secure resource that is accessible by an realm with user and password specified.
db-password
digest-algorithmNMD5support all algorithms in JDK, and also "none"
encodingNHex if there is a digest-algorithm,
no encoding if digest is not defined
Hex, Base64, not specified (no encoding)
charsetN charset for digest

In GlassFish, a security feature allows you to specify a username and password in the JDBCRealm instead of in the connection pool. By doing this, other applications cannot look up the datasource and get a connection to browse the user-name, password database tables.

How to use JDBCRealm in a JavaEE application?

  1. Create database tables for the JDBCRealm.
    For example, if you are using Derby, you would create database tables as shown in the following code example:
    create table usertable(userid varchar(10) not null, password varchar(32) not null, primary key(userid));
    create table grouptable(userid varchar(10) not null, groupid varchar(20) not null, primary key(userid, groupid));
    alter table grouptable add constraint FK_USERID foreign key(userid) references usertable(userid);
    	
  2. Create a JDBCRealm using the Admin Console.
    For instance, one can create a JDBCRealm with the following properties:
    Property NameProperty Value
    datasource-jndijdbc/security
    user-tableusertable
    user-name-columnuserid
    password-columnpassword
    group-tablegrouptable
    group-name-columngroupid
    jaas-contextjdbcRealm
    where jdbc/security is a datasource can access the tables above.
  3. Specify that the JDBCRealm is the realm to be used as the realm for the application. This is specified in the deployment descriptor: sun-application.xml (for EAR) or, web.xml (for WAR) or sun-ejb-jar.xml (for EJB JAR).
  4. Make sure that you have <security-role-mapping> in sun-\*.xml. For instance,
      <security-role-mapping>
        <role-name>Employee</role-name>
        <principal-name>Calvin</principal-name>
      </security-role-mapping>
  5. Create a user in database. There is no administration tools for creating users for JDBCRealm. A snapshot of a program that can be used to create users in JDBCRealm is as follows:
        ...
        private static final String userSql = "insert into usertable values(?, ?)";
        private static final String groupSql = "insert into grouptable values(?, ?)";
    
        private static String hashPassword(String password) throws Exception {
            ...
            //compute digest
            ...
            //encode the bytes
    	...
        }
    
        public static void main(String args[]) throws Exception {
            ...
            Class.forName(driver);
            String hPassword = hashPassword(password);
            Connection conn = DriverManager.getConnection(
                jdbcUrl, dbUser, dbPassword);
            PreparedStatement userStmt = conn.prepareStatement(userSql);
            userStmt.setString(1, user); userStmt.setString(2, hPassword);
            userStmt.executeUpdate();
            userStmt.close();
            ...
        }
    
    The sample program can be found in here. When we run the program, please make sure that the JDBC driver is included in CLASSPATH, for instance, $GLASSFISH_HOME/javadb/lib/derbyclient.jar

Notes on Migration

Consider the following differnces when migrating applications from Tomcat and/or JBoss to GlassFish:

  • In Tomcat and JBoss, there is no default. This corresponds to digest-algorithm="none" in GlassFish.
  • In GlassFish and Tomcat, the default encoding is Hex if there is a digest defined. In JBoss, the default encoding is Base64 if there is a digest defined.

Note: Based on comments, I have updated the SQL for creating grouptable.

Comments:

Is the JDBCRealm implementation available as an independent module or a jar so we can plug it into our GlassFish FCS bits? We dont want to move to a nightly or promoted build nor wait for next formally release of Glassfish for this.

Posted by guest on June 08, 2006 at 10:45 AM PDT #

Currently, the implementation is only in v2 builds. I can point you to source files that I changed and you should be able to apply it to FCS bits. Let me know if that will work for you.

Posted by Shing Wai Chan on June 13, 2006 at 02:54 AM PDT #

The JDBCRealm has been ported back to GlassFish v1 ur1. The classname is com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm

Posted by Shing Wai Chan on July 20, 2006 at 08:38 AM PDT #

I noticed that in your example you made grouptable have the column userid as a primary key. Does this mean that with JDBCRealm a user can only be a member of one group at a time? I belive that FileRealm allows a user to be a member of multiple groups.

Posted by Jon on September 27, 2006 at 06:30 AM PDT #

One more interesting question - can I do logon programmatically in GlassFish, so I could assign a role to user basing on some other attributes - such as user status (available/blocked) etc. ?

Posted by vatel on November 01, 2006 at 07:39 AM PST #

I think the SQL above shoud be below. create table grouptable(userid varchar(10) not null, groupid varchar(20) not null, primary key(userid, groupid));

Posted by tk on January 12, 2007 at 10:33 PM PST #

What about roles?

Posted by Paul Morris on February 14, 2007 at 07:25 AM PST #

Can you pls clarify step 4 <security-role-mapping>?
  <security-role-mapping>
    <role-name>Employee</role-name>
    <principal-name>Calvin</principal-name>
  </security-role-mapping>

I tried to put this in both web.xml and sun-web.xml in both cases it is considered invalid content.

Posted by tmike on February 15, 2007 at 01:42 PM PST #

tmike, you have to insert roles in web.xml too: <security-role> <description/> <role-name>changeAccountStatus</role-name> </security-role>. I would like to get the JDBCRealm source file modified by Shing Wai Chan.

Posted by Alexandre on March 07, 2007 at 03:53 AM PST #

Thank you a million times for this. I have been researching this topic for two weeks now (JAAS, especially authorization). Everybody gives file-based examples, or provides dictionary-level explanations. You put it into 1-2-3 for me! Thanks!

Posted by HandyGeek on June 29, 2007 at 05:12 AM PDT #

Hi all! I have a table of users in my database which I sue for various other tasks in my system. Since they need to be users of the AS I made the necessary routines to keep my table sinchonized with the file realm of the AS. Now with the new glassfish I get IDBC realms which is great news. I tried to do it with Derby and it worked fine. My problem is that I need to use PostgreSQL (latest version) and I can't make it work. I switch the pool only and it simply doesn't work.

Does anyone knows or have the slightest idea of why it doesn't work with PostgreSQL?

I'm surprised about the lack of information about this kind of things... man... it's easier to find Bin Laden than to find why Glassfish cannot authenticate users against PostgreSQL.

Anticipated thanks,
Mario

Posted by Mario Umpiérrez on August 25, 2007 at 10:40 AM PDT #

Could you please specify step 3: What shoud I put into the sun-application.xml
(Or: into application-client.xml / sun-application-client.xml - I don't have an sun-application.xml...)

sorry, I'm new to this topic and can't find anywhere else an example for what should be inserted to the xml for correctly specifying the JDBCRealm to be used....
Thanks

Posted by ralf on October 14, 2007 at 05:59 PM PDT #

Thank's very mach ! short and easy undestand description. (sorry my english :-( )

Posted by Vitaly Mayatnikov on February 23, 2008 at 08:50 PM PST #

Does this realm support dynamic editing of the user database? In other words, if i add a user to a certain group in the database from within my webapplication will that user be able to authenticate after that without me having to restart Glassfish?
Basicly this comes down to weather or not the realm checks the database for every authentication or weather it staticly caches everything when glassfish starts ?

Posted by Stijn on March 12, 2008 at 10:09 PM PDT #

In what jar can i find the com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm class? I want to use it programaticly to call the digest method (or so I read on the web). After it computes my digested password, i save it into the database.

Posted by Alex Burada on March 18, 2008 at 07:20 AM PDT #

When using a jdbc realm, the server first authentificates the user with the specified jdbc realm, then using the default realm. So if the default realm is fileRealm, auhtentification fails because the fileRealm doesn't have the users from jdbcRealm. Is this a bug or have I done something wrong?

Posted by Alex Burada on March 22, 2008 at 10:49 PM PDT #

My application (currently in tomcat 6.0) allows the admin users to create new guestuser at runtime by making entry in the database realm table. So I can dynamically add new users and delete users. I need to migrate my application on Glassfish v2ur2. But there is a problem.

Whenever I am creating a new user from my web application I have to make
entry in sun-web.xml
<security-role-mapping>
<role-name>guest</role-name>
<principal-name> newly_added_user_name </principal-name>
</security-role-mapping>
and then restart the glassfish or else the application throws an error : HTTP Status 403 - Access to the requested resource has been denied.
It doesn't identifies the user.

Can't it behave the same way Tomcat was behaving. My application has the functionality to create dynamic users and I need to have it in Glassfish. Please help

Posted by Pratham on July 11, 2008 at 05:48 PM PDT #

pffff each time i try to save jdbcRealm configuration through GlassFish administration panel i get this error

Caused by: com.sun.enterprise.security.auth.realm.BadRealmException: com.sun.enterprise.security.auth.realm.BadRealmException: Missing required
property user-name-column for JDBCRealm.

This error appears for each required field. Where is the bug ? In my mind or in GlassFish ? Did anybody make authentication working without JAAS ?

Posted by Babas on August 05, 2008 at 07:53 PM PDT #

I haven't test jdbcRealm, it seems pretty straightforward to implement. However I am wondering about one thing:
1) Is there a way to specify a custom digest algorithm?

Posted by Federico Alcantara on August 05, 2008 at 08:31 PM PDT #

Can I have got a access to HttpRequest/Session from JdbcRealm or CustomLoginModule?

Posted by Petka on October 13, 2008 at 06:58 PM PDT #

In regard to question by Pratham (403 Error). Take a look here: http://blogs.sun.com/bobby/entry/simplified_security_role_mapping. You need to go to Configuration -> Security in the admin console. Click Enabled next to Default Principal to Role Mapping and Save.

Posted by Dima Chornyi on July 02, 2009 at 05:36 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

Shing Wai Chan

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today