X

Technology insights, news and tips.

  • Sun
    June 8, 2006

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.

Join the discussion

Comments ( 21 )
  • guest Thursday, June 8, 2006
    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.
  • Shing Wai Chan Tuesday, June 13, 2006
    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.
  • Shing Wai Chan Thursday, July 20, 2006
    The JDBCRealm has been ported back to GlassFish v1 ur1. The classname is com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm
  • Jon Wednesday, September 27, 2006
    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.
  • vatel Wednesday, November 1, 2006
    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. ?
  • tk Saturday, January 13, 2007
    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));
  • Paul Morris Wednesday, February 14, 2007
    What about roles?
  • tmike Thursday, February 15, 2007
    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.
  • Alexandre Wednesday, March 7, 2007
    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.
  • HandyGeek Friday, June 29, 2007
    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!
  • Mario Umpi&eacute;rrez Saturday, August 25, 2007

    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


  • ralf Monday, October 15, 2007

    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


  • Vitaly Mayatnikov Sunday, February 24, 2008

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


  • Stijn Thursday, March 13, 2008

    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 ?


  • Alex Burada Tuesday, March 18, 2008

    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.


  • Alex Burada Sunday, March 23, 2008

    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?


  • Pratham Saturday, July 12, 2008

    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


  • Babas Wednesday, August 6, 2008

    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 ?


  • Federico Alcantara Wednesday, August 6, 2008

    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?


  • Petka Tuesday, October 14, 2008

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


  • Dima Chornyi Thursday, July 2, 2009

    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.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.