users@glassfish.java.net

Re: RE: How do I add (and edit/delete) a user programmatically from a java

From: <glassfish_at_javadesktop.org>
Date: Fri, 22 Aug 2008 15:05:55 PDT

Switching to the JDBC realm worked great. Hear are some scribbles I jotted down while switching in case it helps someone else who stumbles upon this thread trying to do the same thing. Note I'm not sure if I kept these notes 100% up to date, they could have something I backed out and they could be missing something:

Create pool.
Name: userauth
Resource Type: javax.sql.DataSource
Database Vendor: JavaDB?, I picked Derby instead

Needed to add these properties to the pool:
databaseName=userauth
Password=<your systems password here>
connectionAttributes=;create=true

already defaults:
User=APP
ServerName=localhost
PortNumber=1527

Make sure you can ping it.

Create JDBC resource.
JNDI Name: jdbc/userauth
Pool Name: userauth <- Needs to match pool name above
Description: User Authentication
Status: enabled


Create Realm:
Name: userauth
Class: *.JDBCRealm
JNDI: jdbc/userauth <- Needs to match resource above
User Table: USERTABLE
User Name Column: USERID
Password Column: PASSWORD
Group Table: GROUPTABLE
Group Name Column: GROUPID
Assign Group:
Database User: APP
Database Password: <your systems password here>
Digest Algorithm: MD5
Encoding:


JAAS context: jdbcRealm

(Plan to try removing username and password from connection pool, I think they are redundant if they are listed with the realm)

Add a new database connection in netbeans:
Java DB (Network)
the derby driver
jdbc:derby://localhost:1527/userauth
User Name: APP
Password: <your systems password here>

Run a *.sql file to create tables and first users:

-- Create tables for JDBC realm
CREATE TABLE USERTABLE (
    USERID VARCHAR(32) NOT NULL CONSTRAINT USER_PK PRIMARY KEY,
    PASSWORD VARCHAR(32) NOT NULL
);

CREATE TABLE GROUPTABLE (
    USERID VARCHAR(32) NOT NULL,
    GROUPID VARCHAR(32) NOT NULL,
    CONSTRAINT GROUP_FK PRIMARY KEY(USERID, GROUPID),
    CONSTRAINT USER_FK FOREIGN KEY(USERID) REFERENCES USERTABLE(USERID)
        ON DELETE CASCADE ON UPDATE RESTRICT
);

CREATE TABLE USERINFOTABLE (
    USERID VARCHAR(32) NOT NULL,
    FIRSTNAME VARCHAR(32),
    LASTNAME VARCHAR(32),
    EMAIL VARCHAR(100),
    CONSTRAINT USERINFO_FK FOREIGN KEY(USERID) REFERENCES USERTABLE(USERID)
        ON DELETE CASCADE ON UPDATE RESTRICT
);

INSERT INTO USERTABLE(USERID,PASSWORD) VALUES ('bankadmin', <insert scrambled password here>);
INSERT INTO GROUPTABLE(USERID,GROUPID) VALUES ('bankadmin', 'bankAdmin');
INSERT INTO USERINFOTABLE(USERID,FIRSTNAME,LASTNAME,EMAIL) VALUES ('bankadmin', 'delete or edit me', 'blabla', '');

INSERT INTO USERTABLE(USERID,PASSWORD) VALUES ('200', <insert scrambled password here>);
INSERT INTO GROUPTABLE(USERID,GROUPID) VALUES ('200', 'bankCustomer');
INSERT INTO USERINFOTABLE(USERID,FIRSTNAME,LASTNAME,EMAIL) VALUES ('200', 'delete or edit me', 'blabla', '');

To get the scrambled password, I used this code (don't include the "MD5: " prefix in the database):

package com.sun.tutorial.javaee.dukesbank.util;

import java.security.MessageDigest;
import java.math.BigInteger;

public class OneWayHashPerformer
{
    public static void main( String args[] ) throws Exception
    {
        String s = "<plaintext password here>";
        MessageDigest m = MessageDigest.getInstance( "MD5" );
        m.update( s.getBytes(), 0, s.length() );
        System.out.println( "MD5: " + new BigInteger( 1, m.digest()).toString( 16 ) );
    }
}



To specify the realm, modify the appropriate deployment descriptor for your application:

Added this to sun-web.xml (in dukesbank-war) and to sun-ejb-jar.xml (in dukesbank-ejb under the sun-ejb-jar element):

    <security-role-mapping>
        <role-name>bankAdmin</role-name>
        <group-name>bankAdmin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>bankCustomer</role-name>
        <group-name>bankCustomer</group-name>
    </security-role-mapping>

Change realm name from file to userauth under web-app\login-config\realm-name in web.xml (in dukesbank-war).

sun-application.xml for the top level project (holder of all three sub projects):
Was already mapped groups to roles.
Add realm element to it:
<realm>userauth</realm>

Perhaps sun-ejb-jar.xml doesn't need a realm because the calls are local and not via web services (not to be confused with web client). Or it’s covered by the top level sun-application.xml file.

------
Some related links:
http://docs.sun.com/app/docs/doc/819-3660/6n5s7klpf?a=view
http://docs.sun.com/app/docs/doc/819-3671/abloe?a=view
http://docs.sun.com/app/docs/doc/819-3672/beabr?a=view
http://docs.sun.com/app/docs/doc/819-3673/6n5sk1d5b?a=view
http://java.sun.com/javaee/5/docs/tutorial/backup/doc/Security-JavaEE3.html
http://developers.sun.com/appserver/reference/techart/as8_authentication/index.html
http://java.sun.com/javase/technologies/security/
http://blogs.sun.com/foo/entry/mort_learns_jdbc_for_glassfish
http://blogs.sun.com/foo/entry/mort_learns_jdbc_realm_authentication
http://codepimpsdotorg.blogspot.com/2007/12/glassfish-jdbc-realm-authentication.html
http://blogs.sun.com/swchan/entry/jdbcrealm_in_glassfish
http://www.sun.com/software/dtd/appserver/

-----

Later I did this to switch which databases is used for passwords:
Switch databaseName in userauth connection pool from userauth to sun-appserv-samples
Removed SecurityMechanism=4 (fixed a wrong username/password issue)
Realm's JNDI references JDBC Resource JNDI which specifies which connection pool to use which must have the correct database name, so it must stay as userauth.

Note that I think none of the database references in netbeans reference the JDBC resource JNDI's. They are "database URL's" in the form of jdbc:derby://<HOST>[:<PORT>]/databaseName[;attr1=value1[;...]]
The APP_dukesbank-ejb.dbschema file also uses a database URL
Connection pools may only be getting used by web clients (and web services too perhaps).
[Message sent by forum member 'markkr2' (markkr2)]

http://forums.java.net/jive/thread.jspa?messageID=294920