Wednesday, December 14, 2011

JAAS and Derby

Did you read the previous document about JAAS and Sun Application Server? That implemented a file

based JAAS security handling. I wanted to experiment with a database solution which in my humble opinion is better,

since it more distributable (to name just one advantage)

To give credit where it is due, it took almost everything form here.

You only need to do four things, and those are quite simple.

Fix database

I use to default tablespace that comes with the Derby database. That is in the latest versions of Java a Derby database is shipped.

The standard way to work with it is to start it either from the application servers asadamin, with command, asadmin start-database or stand alone.

This is the necessary data you need by default

url: jdbc:derby://localhost:1527/sun-appserv-samples

uid: APP

pwd: APP

A connection pool is set up in the Application Server that goes towards this database. You do not need to do anything besides start the app server.

Just run these and everything will be ok. Then your database will be populated with the correct tables.

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));
alter table grouptable add constraint FK_USERID
foreign key(userid) references usertable(userid);

Note that the default handling of pwd will be hex so you cannot add a plain text password manually
into the database. This will fail.

Thus, log into the Derby database, with squirrel or something else. Then execute the three scripts above.

Create realm in Sun Application Server
Create this realm in the admin console. You do this by doing this;

log in to admin console with http://localhost:4848, go to
Configuration->Security->Realms. Since I had created my realm previously I saw it here. If you haven't
just create a new one here.
Make sure that className is JdbcRealm. Then a lot of textboxes will appear. Fill in those so that they look like below.


Property NameProperty Value
datasource-jndi jdbc/security
user-table usertable
user-name-column userid
password-column password
group-table grouptable
group-name-column groupid
jaas-context jdbcRealm
Add the html files
In the previous example we added the necessary files, but here is a replay.




Sun-web.xml file

These files indicate the userid and groupid.




/WebApplication1

jonas_admins
jonas





Keep a copy of the generated servlet class' java code.





login.html












User Name:
Password :





index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>





JSP Page


Hello World!





web.xml




30



index.jsp



restricted
/*


jonas_admins








unrestricted stylesheets

/css/*
GET




FORM
jonas_realm

/login.html

/loginerror.html





jonas_admins




That's it. Just deploy the app and it will work. You will be forced to add a uid/pwd to be accepted.
The file to add users/pwds in the database in hex format can be found below, taken from Sun.



File to populate database with pwd in hex

import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class CreateJdbcRealmUser {
private static final String driver = "org.apache.derby.jdbc.ClientDriver";
private static final String jdbcUrl = "jdbc:derby://localhost:1527/sun-appserv-samples";
private static final String userSql = "insert into usertable values(?, ?)";
private static final String groupSql = "insert into grouptable values(?, ?)";

private static final char[] HEXADECIMAL = { '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

private static String hashPassword(String password) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();

byte[] bytes = md.digest(password.getBytes());
StringBuilder sb = new StringBuilder(2 * bytes.length);
for (int i = 0; i < bytes.length; i++) {
int low = (int)(bytes[i] & 0x0f);
int high = (int)((bytes[i] & 0xf0) >> 4);
sb.append(HEXADECIMAL[high]);
sb.append(HEXADECIMAL[low]);
}
return sb.toString();
}

public static void main(String args[]) throws Exception {
String dbUser = null;
String dbPassword = null;
String user = null;
String password = null;
String group = null;

if (args.length != 5){
System.err.println("Usage java CreateJDBCRealmUser ");
System.exit(2);
} else {
dbUser = args[0];
dbPassword = args[1];
user = args[2];
password = args[3];
group = args[4];
}

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();

PreparedStatement groupStmt = conn.prepareStatement(groupSql);
groupStmt.setString(1, user);
groupStmt.setString(2, group);
groupStmt.executeUpdate();
groupStmt.close();

conn.close();
}
}

0 comments:

Post a Comment