/*
* Copyright 2006 Rui Damas <rui.damas at gmail com>
* Distributed under the terms of either:
* - the common development and distribution license (CDDL), v1.0; or
* - the GNU Lesser General Public License, v2.1 or later
*/
package contrib.winstone;
import java.sql.*;
import java.util.*;
import winstone.*;
/**
* A JDBC authentication realm to be used with Winstone Servelet container.
* <p>
* --JDBCRealm.url and --JDBCRealm.user are required.
* </p>
*
* @author Rui Damas
*/
public class JDBCRealm implements AuthenticationRealm {
// Command line arguments prefix
public static String ARGS = "JDBCRealm.";
// Command line arguments for connecting
public static String
ARGS_DRIVER = ARGS + "driver",
ARGS_URL = ARGS + "url",
ARGS_USER = ARGS + "user",
ARGS_PASSWORD = ARGS + "password";
// Command line arguments to SQL identifiers
public static String
ARGS_USER_REL = ARGS + "userRel",
ARGS_USER_NAME_COL = ARGS + "userNameCol",
ARGS_USER_CRED_COL = ARGS + "userCredCol",
ARGS_USER_ROLE_REL = ARGS + "userRoleRel",
ARGS_ROLE_NAME_COL = ARGS + "roleNameCol";
// Defaults for SQL identifiers
public static String
DEFAULT_USER_REL = "web_users",
DEFAULT_USER_NAME_COL = "username",
DEFAULT_USER_CRED_COL ="credential",
DEFAULT_USER_ROLE_REL = "web_user_roles",
DEFAULT_ROLE_NAME_COL = "rolename";
private Connection connection;
private final String url, user, password,
retriveUserQuery, authenticationQueryPostfix, userRolesQuery;
/**
Creates a new instance of JDBCAuthenticationRealm.
<p>
If a <code>"JDBCRealm.driver"</code> exists in the <code>args</code>
map an atempt to load the class will be made and
a success message will be printed to <code>System.out</code>,
or, if the class fails to load,
an error message will be printed to <code>System.err</code>.
</p>
*/
public JDBCRealm(Set rolesAllowed, Map<String, String> args) {
// Get connection arguments
String driver = args.get(ARGS_DRIVER),
url = args.get(ARGS_URL),
user = args.get(ARGS_USER),
password = args.get(ARGS_PASSWORD);
this.url = url;
this.user = user;
this.password = password;
// Get SQL identifier arguments
String userRel = args.get(ARGS_USER_REL),
userNameCol = args.get(ARGS_USER_NAME_COL),
userCredCol = args.get(ARGS_USER_CRED_COL),
userRoleRel = args.get(ARGS_USER_ROLE_REL),
roleNameCol = args.get(ARGS_ROLE_NAME_COL);
// Get defaults if necessary
if (userRel == null) userRel = DEFAULT_USER_REL;
if (userNameCol == null) userNameCol = DEFAULT_USER_NAME_COL;
if (userCredCol == null) userCredCol = DEFAULT_USER_CRED_COL;
if (userRoleRel == null) userRoleRel = DEFAULT_USER_ROLE_REL;
if (roleNameCol == null) roleNameCol = DEFAULT_ROLE_NAME_COL;
retriveUserQuery =
"SELECT 1\n" +
" FROM \"" + userRel + "\"\n" +
" WHERE \"" + userNameCol + "\" = ?";
// Prepare query prefixes
authenticationQueryPostfix =
"\n AND \"" + userCredCol + "\" = ?";
userRolesQuery =
"SELECT \"" + roleNameCol + "\"\n" +
" FROM \"" + userRoleRel + "\"\n" +
" WHERE \"" + userNameCol + "\" = ?";
// If the driver was specified
if (driver != null)
try {
// Try to load the driver
Class.forName(driver);
// and notify if loaded
System.out.println("JDBCRealm loaded jdbc driver: " + driver);}
catch (ClassNotFoundException cnfe) {
// Notify if fails
System.err.println(
"JDBCRealm failed to load jdbc driver: "+ driver);}
}
public AuthenticationPrincipal getPrincipal
(String userName, String password, boolean usePassword) {
try {
// Get a connection
if ((connection == null) || connection.isClosed())
connection = DriverManager.getConnection(url, user, password);
// Query for user
String query = retriveUserQuery;
if (usePassword) query = query + authenticationQueryPostfix;
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, userName);
if (usePassword) ps.setString(2, password);
ResultSet resultSet = ps.executeQuery();
// If there is a user (row)
if (resultSet.next()) {
// Query for the user roles
query = userRolesQuery;
ps = connection.prepareStatement(query);
ps.setString(1, userName);
resultSet = ps.executeQuery();
// Load list
List<String> roles = new Vector<String>();
while (resultSet.next())
roles.add(resultSet.getString(1));
return new AuthenticationPrincipal(userName, password, roles);
}
}
catch (SQLException sqle) {sqle.printStackTrace();}
return null;
}
/**
* Authenticate the user - do we know them ? Return a distinct id once we
* know them.
* @return <code>getPrincipal(userName, password, true);</code>
*/
public AuthenticationPrincipal authenticateByUsernamePassword
(String userName, String password) {
return getPrincipal(userName, password, true);
}
/**
* Retrieve an authenticated user
* @return <code>getPrincipal(userName, password, false);</code>
*/
public AuthenticationPrincipal retrieveUser(String userName) {
return getPrincipal(userName, null, false);
}
}