JDBCRealmpublic final class JDBCRealm extends com.sun.enterprise.security.auth.realm.IASRealm Realm for supporting JDBC authentication.
The JDBC realm needs the following properties in its configuration:
- jaas-context : JAAS context name used to access LoginModule for
authentication (for example JDBCRealm).
- datasource-jndi : jndi name of datasource
- db-user : user name to access the datasource
- db-password : password to access the datasource
- digest: digest mechanism
- charset: charset encoding
- user-table: table containing user name and password
- group-table: table containing user name and group name
- user-name-column: column corresponding to user name in user-table and group-table
- password-column : column corresponding to password in user-table
- group-name-column : column corresponding to group in group-table
|
Fields Summary |
---|
public static final String | AUTH_TYPE | public static final String | PARAM_DATASOURCE_JNDI | public static final String | PARAM_DB_USER | public static final String | PARAM_DB_PASSWORD | public static final String | PARAM_DIGEST_ALGORITHM | public static final String | DEFAULT_DIGEST_ALGORITHM | public static final String | NONE | public static final String | PARAM_ENCODING | public static final String | HEX | public static final String | BASE64 | public static final String | DEFAULT_ENCODING | public static final String | PARAM_CHARSET | public static final String | PARAM_USER_TABLE | public static final String | PARAM_USER_NAME_COLUMN | public static final String | PARAM_PASSWORD_COLUMN | public static final String | PARAM_GROUP_TABLE | public static final String | PARAM_GROUP_NAME_COLUMN | private static final char[] | HEXADECIMAL | private Map | groupCache | private Vector | emptyVector | private String | passwordQuery | private String | groupQuery | private MessageDigest | md |
Methods Summary |
---|
public java.lang.String[] | authenticate(java.lang.String username, java.lang.String password)Invoke the native authentication call.
String[] groups = null;
if (isUserValid(username, password)) {
groups = findGroups(username);
groups = addAssignGroups(groups);
setGroupNames(username, groups);
}
return groups;
| private java.lang.String | base64Encode(byte[] bytes)
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(bytes);
| private void | close(java.sql.Connection conn, java.sql.PreparedStatement stmt, java.sql.ResultSet rs)
if (rs != null) {
try {
rs.close();
} catch(Exception ex) {
}
}
if (stmt != null) {
try {
stmt.close();
} catch(Exception ex) {
}
}
if (conn != null) {
try {
conn.close();
} catch(Exception ex) {
}
}
| private java.lang.String[] | findGroups(java.lang.String user)Delegate method for retreiving users groups
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
try{
connection = getConnection();
statement = connection.prepareStatement(groupQuery);
statement.setString(1, user);
rs = statement.executeQuery();
final List<String> groups = new ArrayList<String>();
while (rs.next()) {
groups.add(rs.getString(1));
}
final String[] groupArray = new String[groups.size()];
return groups.toArray(groupArray);
} catch(Exception ex) {
_logger.log(Level.SEVERE, "jdbcrealm.grouperror", user);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Cannot load group", ex);
}
return null;
} finally {
close(connection, statement, rs);
}
| public java.lang.String | getAuthType()Returns a short (preferably less than fifteen characters) description
of the kind of authentication which is supported by this realm.
return AUTH_TYPE;
| private java.sql.Connection | getConnection()Return a connection from the properties configured
final String dsJndi = this.getProperty(PARAM_DATASOURCE_JNDI);
final String dbUser = this.getProperty(PARAM_DB_USER);
final String dbPassword = this.getProperty(PARAM_DB_PASSWORD);
try{
final DataSource dataSource =
(DataSource)ConnectorRuntime.getRuntime().lookupNonTxResource(dsJndi,false);
Connection connection = null;
if (dbUser != null && dbPassword != null) {
connection = dataSource.getConnection(dbUser, dbPassword);
} else {
connection = dataSource.getConnection();
}
return connection;
} catch(Exception ex) {
String msg = sm.getString("jdbcrealm.cantconnect", dsJndi, dbUser);
LoginException loginEx = new LoginException(msg);
loginEx.initCause(ex);
throw loginEx;
}
| public java.util.Enumeration | getGroupNames(java.lang.String username)Returns the name of all the groups that this user belongs to.
It loads the result from groupCache first.
This is called from web path group verification, though
it should not be.
Vector vector = groupCache.get(username);
if (vector == null) {
String[] grps = findGroups(username);
setGroupNames(username, grps);
vector = groupCache.get(username);
}
return vector.elements();
| private java.lang.String | hashPassword(java.lang.String password)
String result = null;
byte[] bytes = null;
String charSet = getProperty(PARAM_CHARSET);
if (charSet != null) {
bytes = password.getBytes(charSet);
} else {
bytes = password.getBytes();
}
if (md != null) {
synchronized(md) {
md.reset();
bytes = md.digest(bytes);
}
}
String encoding = getProperty(PARAM_ENCODING);
if (HEX.equalsIgnoreCase(encoding)) {
result = hexEncode(bytes);
} else if (BASE64.equalsIgnoreCase(encoding)) {
result = base64Encode(bytes);
} else { // no encoding specified
result = new String(bytes);
}
return result;
| private java.lang.String | hexEncode(byte[] bytes)
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 synchronized void | init(java.util.Properties props)Initialize a realm with some properties. This can be used
when instantiating realms from their descriptions. This
method may only be called a single time.
super.init(props);
String jaasCtx = props.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
String dbUser = props.getProperty(PARAM_DB_USER);
String dbPassword = props.getProperty(PARAM_DB_PASSWORD);
String dsJndi = props.getProperty(PARAM_DATASOURCE_JNDI);
String digestAlgorithm = props.getProperty(PARAM_DIGEST_ALGORITHM,
DEFAULT_DIGEST_ALGORITHM);
String encoding = props.getProperty(PARAM_ENCODING);
String charset = props.getProperty(PARAM_CHARSET);
String userTable = props.getProperty(PARAM_USER_TABLE);
String userNameColumn = props.getProperty(PARAM_USER_NAME_COLUMN);
String passwordColumn = props.getProperty(PARAM_PASSWORD_COLUMN);
String groupTable = props.getProperty(PARAM_GROUP_TABLE);
String groupNameColumn = props.getProperty(PARAM_GROUP_NAME_COLUMN);
if (jaasCtx == null) {
String msg = sm.getString(
"realm.missingprop", IASRealm.JAAS_CONTEXT_PARAM, "JDBCRealm");
throw new BadRealmException(msg);
}
if (dsJndi == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_DATASOURCE_JNDI, "JDBCRealm");
throw new BadRealmException(msg);
}
if (userTable == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_USER_TABLE, "JDBCRealm");
throw new BadRealmException(msg);
}
if (groupTable == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_GROUP_TABLE, "JDBCRealm");
throw new BadRealmException(msg);
}
if (userNameColumn == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_USER_NAME_COLUMN, "JDBCRealm");
throw new BadRealmException(msg);
}
if (passwordColumn == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_PASSWORD_COLUMN, "JDBCRealm");
throw new BadRealmException(msg);
}
if (groupNameColumn == null) {
String msg = sm.getString(
"realm.missingprop", PARAM_GROUP_NAME_COLUMN, "JDBCRealm");
throw new BadRealmException(msg);
}
passwordQuery = "SELECT " + passwordColumn + " FROM " + userTable +
" WHERE " + userNameColumn + " = ?";
groupQuery = "SELECT " + groupNameColumn + " FROM " + groupTable +
" WHERE " + userNameColumn + " = ? ";
if (!NONE.equalsIgnoreCase(digestAlgorithm)) {
try {
md = MessageDigest.getInstance(digestAlgorithm);
} catch(NoSuchAlgorithmException e) {
String msg = sm.getString("jdbcrealm.notsupportdigestalg",
digestAlgorithm);
throw new BadRealmException(msg);
}
}
if (md != null && encoding == null) {
encoding = DEFAULT_ENCODING;
}
this.setProperty(IASRealm.JAAS_CONTEXT_PARAM, jaasCtx);
if (dbUser != null && dbPassword != null) {
this.setProperty(PARAM_DB_USER, dbUser);
this.setProperty(PARAM_DB_PASSWORD, dbPassword);
}
this.setProperty(PARAM_DATASOURCE_JNDI, dsJndi);
this.setProperty(PARAM_DIGEST_ALGORITHM, digestAlgorithm);
if (encoding != null) {
this.setProperty(PARAM_ENCODING, encoding);
}
if (charset != null) {
this.setProperty(PARAM_CHARSET, charset);
}
if (_logger.isLoggable(Level.FINEST)) {
_logger.finest("JDBCRealm : " +
IASRealm.JAAS_CONTEXT_PARAM + "= " + jaasCtx + ", " +
PARAM_DATASOURCE_JNDI + " = " + dsJndi + ", " +
PARAM_DB_USER + " = " + dbUser + ", " +
PARAM_DIGEST_ALGORITHM + " = " + digestAlgorithm + ", " +
PARAM_ENCODING + " = " + encoding + ", " +
PARAM_CHARSET + " = " + charset);
}
groupCache = new HashMap<String, Vector>();
emptyVector = new Vector<String>();
| private boolean | isUserValid(java.lang.String user, java.lang.String password)Test if a user is valid
Connection connection = null;
PreparedStatement statement = null;
ResultSet rs = null;
boolean valid = false;
try {
String hpwd = hashPassword(password);
connection = getConnection();
statement = connection.prepareStatement(passwordQuery);
statement.setString(1, user);
rs = statement.executeQuery();
String pwd = null;
if (rs.next()) {
pwd = rs.getString(1);
if (HEX.equalsIgnoreCase(getProperty(PARAM_ENCODING))) {
valid = pwd.equalsIgnoreCase(hpwd);
} else {
valid = pwd.equals(hpwd);
}
}
} catch(Exception ex) {
_logger.log(Level.SEVERE, "jdbcrealm.invaliduser", user);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Cannot validate user", ex);
}
} finally {
close(connection, statement, rs);
}
return valid;
| private void | setGroupNames(java.lang.String username, java.lang.String[] groups)
Vector<String> v = null;
if (groups == null) {
v = emptyVector;
} else {
v = new Vector<String>(groups.length + 1);
for (int i=0; i<groups.length; i++) {
v.add(groups[i]);
}
}
synchronized (this) {
groupCache.put(username, v);
}
|
|