You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by na...@apache.org on 2001/07/14 05:20:37 UTC
cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa RealmBase.java SimpleRealm.java JDBCRealm.java
nacho 01/07/13 20:20:37
Modified: src/share/org/apache/tomcat/modules/aaa SimpleRealm.java
JDBCRealm.java
Added: src/share/org/apache/tomcat/modules/aaa RealmBase.java
Log:
* Added RealmBase to simplify a bit Realms writing
* Used RealmBase in Simple Realm to allow use of digested passwords. there.
* Used RealmBase in JDBCRealm.
and ported this fix to JDBCRealm from Tomcat 3.2. branch
Bug# 2149 , 727 ( possibly others )
JDBCRealm did not close all the prepared staments opened,
when trying to reconnect when found a broken DBConnection,
I'ts a problem specillay surfaced when using MySQL..
Reported By :
mark.shotton at micromass.co.uk
andre.gommlich at netkom.de
edwin at finalist.com
kaneda at dedaletechnology.com
Revision Changes Path
1.3 +44 -57 jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/SimpleRealm.java
Index: SimpleRealm.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/SimpleRealm.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- SimpleRealm.java 2001/02/27 19:10:17 1.2
+++ SimpleRealm.java 2001/07/14 03:20:37 1.3
@@ -85,17 +85,12 @@
* specialized in extracting the information from the request.
*
*/
-public class SimpleRealm extends BaseInterceptor {
+public class SimpleRealm extends RealmBase {
MemoryRealm memoryRealm;
-
- int reqRolesNote=-1;
- int userNote=-1;
- int passwordNote=-1;
-
String filename="/conf/users/tomcat-users.xml";
+
-
public SimpleRealm() {
}
@@ -109,17 +104,7 @@
}
// -------------------- Hooks --------------------
- public void engineInit( ContextManager cm )
- throws TomcatException
- {
- reqRolesNote = cm.getNoteId( ContextManager.REQUEST_NOTE,
- "required.roles");
- userNote=cm.getNoteId( ContextManager.REQUEST_NOTE,
- "credentials.user");
- passwordNote=cm.getNoteId( ContextManager.REQUEST_NOTE,
- "credentials.password");
- }
-
+
public void contextInit(Context ctx)
throws TomcatException
{
@@ -137,37 +122,6 @@
}
}
- public int authenticate( Request req, Response response )
- {
- // This realm will use only username and password callbacks
- String user=(String)req.getNote( userNote );
- String password=(String)req.getNote( passwordNote );
- if( user==null) return DECLINED; // we don't know about this
-
- if( debug > 0 ) log( "Verify user=" + user + " pass=" + password );
- SimpleRealmPrincipal srp=memoryRealm.getPrincipal( user );
- if( srp == null ) return DECLINED;
-
- if( srp.checkPassword( password ) ) {
- if( debug > 0 ) log( "Auth ok, user=" + user );
- Context ctx = req.getContext();
- req.setAuthType(ctx.getAuthMethod());
- req.setRemoteUser( user );
- req.setUserPrincipal( srp );
-
- if( user!=null ) {
- String userRoles[] = srp.getUserRoles( user );
- req.setUserRoles( userRoles );
- }
- return OK; // the user is ok, - no need for more work
- }
- return DECLINED; // the user is not known to me - it may
- // be in a different realm.
-
- // XXX maybe we should add "realm-name" - the current behavior
- // is to treat them as "global users"
- }
-
class MemoryRealm {
// String user -> password
// Hashtable passwords=new Hashtable();
@@ -192,7 +146,7 @@
public void addPrincipal( String name, Principal p ) {
principals.put( name, p );
}
-
+
public void addUser(String name, String pass, String groups ) {
if( getDebug() > 0 ) log( "Add user " + name + " " +
pass + " " + groups );
@@ -225,7 +179,7 @@
String user=attributes.getValue("name");
String pass=attributes.getValue("password");
String group=attributes.getValue("roles");
-
+
mr.addUser( user, pass, group );
}
}
@@ -249,11 +203,9 @@
private void addRole(String role ) {
roles.addElement( role );
}
-
- boolean checkPassword( String s ) {
- if( s == pass ) return true; // interned or nulls?
- if( s==null ) return false; // if pass == null already true
- return s.equals( pass );
+
+ String getCredentials() {
+ return pass;
}
// backward compat - bad XML format !!!
@@ -268,7 +220,7 @@
}
}
- String[] getUserRoles( String user ) {
+ String[] getUserRoles( ) {
String rolesA[]=new String[roles.size()];
for( int i=0; i<roles.size(); i++ ) {
rolesA[i]=(String)roles.elementAt( i );
@@ -280,6 +232,41 @@
// return roles.indexOf( role ) >=0 ;
// }
+ }
+
+ /**
+ * getPrincipal
+ * @param username
+ * @return java.security.Principal
+ */
+ protected Principal getPrincipal(String username) {
+ return memoryRealm.getPrincipal( username );
+ }
+
+ /**
+ * getCredentials
+ * @param username
+ * @return java.lang.String
+ */
+ protected String getCredentials(String username) {
+ SimpleRealmPrincipal sp=memoryRealm.getPrincipal( username );
+ if( sp!=null ) {
+ return sp.getCredentials();
+ }
+ return null;
+ }
+
+ /**
+ * getUserRoles
+ * @param username
+ * @return java.lang.String
+ */
+ protected String[] getUserRoles(String username) {
+ SimpleRealmPrincipal sp=memoryRealm.getPrincipal( username );
+ if( sp!=null ) {
+ return sp.getUserRoles();
+ }
+ return null;
}
1.7 +85 -224 jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/JDBCRealm.java
Index: JDBCRealm.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/JDBCRealm.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- JDBCRealm.java 2001/04/10 09:00:59 1.6
+++ JDBCRealm.java 2001/07/14 03:20:37 1.7
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/JDBCRealm.java,v 1.6 2001/04/10 09:00:59 nacho Exp $
- * $Revision: 1.6 $
- * $Date: 2001/04/10 09:00:59 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/JDBCRealm.java,v 1.7 2001/07/14 03:20:37 nacho Exp $
+ * $Revision: 1.7 $
+ * $Date: 2001/07/14 03:20:37 $
*
* The Apache Software License, Version 1.1
*
@@ -62,11 +62,10 @@
package org.apache.tomcat.modules.aaa;
import org.apache.tomcat.core.*;
-import org.apache.tomcat.util.res.StringManager;
-import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.aaa.*;
import java.security.*;
import java.security.Principal;
+
import java.util.Vector;
import java.io.*;
import java.net.*;
@@ -78,21 +77,15 @@
* See the JDBCRealm.howto for more details on how to set up the database and
* for configuration options.
*
- *
- * TODO: - Work on authentication with non-plaintext passwords
- *
- *
* @author Craig R. McClanahan
* @author Carson McDonald
* @author Ignacio J. Ortega
* @author Bip Thelin
*/
-public final class JDBCRealm extends BaseInterceptor {
- int reqRolesNote;
- int userNote;
- int passwordNote;
+public class JDBCRealm extends RealmBase {
// ----------------------------------------------------- Instance Variables
+ private boolean started=false;
/** The connection to the database. */
private Connection dbConnection = null;
@@ -103,47 +96,34 @@
private PreparedStatement preparedRoles = null;
/** The connection URL to use when trying to connect to the databse */
- private String connectionURL = null;
+ protected String connectionURL = null;
/** The connection URL to use when trying to connect to the databse */
- private String connectionName = null;
+ protected String connectionName = null;
/** The connection URL to use when trying to connect to the databse */
- private String connectionPassword = null;
+ protected String connectionPassword = null;
/** The table that holds user data. */
- private String userTable = null;
+ protected String userTable = null;
/** The column in the user table that holds the user's name */
- private String userNameCol = null;
+ protected String userNameCol = null;
/** The column in the user table that holds the user's credintials */
- private String userCredCol = null;
+ protected String userCredCol = null;
/** The table that holds the relation between user's and roles */
- private String userRoleTable = null;
+ protected String userRoleTable = null;
/** The column in the user role table that names a role */
- private String roleNameCol = null;
+ protected String roleNameCol = null;
/** The JDBC driver to use. */
- private String driverName = null;
+ protected String driverName = null;
- /** The string manager for this package. */
- private static StringManager sm = StringManager.getManager("org.apache.tomcat.resources");
-
- /** Has this component been started? */
- private boolean started = false;
-
/** Has the JDBC connection been started? */
- private boolean JDBCstarted = false;
-
- /**
- * Digest algorithm used in passwords thit is same values accepted by MessageDigest for algorithm
- * plus "No" ( no encode ) that is the default
- */
- private String digest = "No";
-
+ protected boolean JDBCStarted = false;
boolean connectOnInit = false;
// ------------------------------------------------------------- Properties
@@ -220,26 +200,6 @@
}
/**
- * Gets the digest algorithm used for credentials in the database
- * could be the same that MessageDigest accepts vor algorithm and "No" that
- * is the Default
- * @return
- */
- public String getDigest() {
- return digest;
- }
-
- /**
- * Sets the digest algorithm used for credentials in the database
- * could be the same that MessageDigest accepts vor algorithm and "No"
- * that is the Default
- * @param algorithm the Encode type
- */
- public void setDigest(String algorithm) {
- digest = algorithm;
- }
-
- /**
* When connectOnInit is true the JDBC connection is started at tomcat init
* if false the connection is started the first times it is needed.
* @param b
@@ -260,72 +220,55 @@
* @param username Username of the Principal to look up
* @param credentials Password or other credentials to use in authenticating this username
*/
- private synchronized boolean checkPassword(String username,String credentials) {
+ public synchronized String getCredentials(String username){
try {
if (!checkConnection())
- return false;
+ return null;
// Create the authentication search prepared statement if necessary
if (preparedAuthenticate == null) {
- String sql = "SELECT " + userCredCol
- + " FROM " + userTable
- + " WHERE " + userNameCol + " = ?";
- if (debug >= 1)
- log("JDBCRealm.authenticate: " + sql);
- preparedAuthenticate = dbConnection.prepareStatement(sql);
+ preparedAuthenticate=getPreparedAuthenticate(dbConnection);
}
// Perform the authentication search
preparedAuthenticate.setString(1, username);
ResultSet rs1 = preparedAuthenticate.executeQuery();
if (rs1.next()) {
- String dbCredentials=rs1.getString(1).trim();
- if( digest.equals("") || digest.equalsIgnoreCase("No")){
- if (credentials.equals(dbCredentials)) {
- if (debug >= 2)
- log(sm.getString("jdbcRealm.authenticateSuccess", username));
- return true;
- }
- } else {
- if (digest(credentials,digest).equals(dbCredentials)) {
- if (debug >= 2)
- log(sm.getString("jdbcRealm.authenticateSuccess", username));
- return true;
- }
- }
+ return rs1.getString(1).trim();
}
rs1.close();
- if (debug >= 2)
- log(sm.getString("jdbcRealm.authenticateFailure", username));
- return false;
+ return null;
} catch (SQLException ex) {
// Log the problem for posterity
- log(sm.getString("jdbcRealm.checkPasswordSQLException", username), ex);
+ log(sm.getString("jdbcRealm.getCredentialsSQLException", username), ex);
// Clean up the JDBC objects so that they get recreated next time
- if (preparedAuthenticate != null) {
- try {
- preparedAuthenticate.close();
- } catch (Throwable t) {
- ;
- }
- preparedAuthenticate = null;
- }
- if (dbConnection != null) {
- try {
- dbConnection.close();
- } catch (Throwable t) {
- ;
- }
- dbConnection = null;
- }
// Return "not authenticated" for this request
- return false;
+ close();
+ return null;
}
}
+ protected PreparedStatement getPreparedAuthenticate(Connection conn) throws SQLException {
+ String sql = "SELECT " + userCredCol
+ + " FROM " + userTable
+ + " WHERE " + userNameCol + " = ?";
+ if (debug >= 1)
+ log("JDBCRealm.authenticate: " + sql);
+ return conn.prepareStatement(sql);
+ }
+
+ protected PreparedStatement getPreparedRoles(Connection conn) throws SQLException {
+ String sql = "SELECT " + roleNameCol + " FROM " + userRoleTable
+ + " WHERE " + userNameCol + " = ?";
+ if (debug >= 1)
+ log("JDBCRealm.roles: " + sql);
+ return conn.prepareStatement(sql);
+ }
+
+
private boolean checkConnection() {
try {
if ((dbConnection == null) || dbConnection.isClosed()) {
Class.forName(driverName);
- if( JDBCstarted )
+ if( JDBCStarted )
log(sm.getString("jdbcRealm.checkConnectionDBClosed"));
if ((connectionName == null || connectionName.equals("")) ||
(connectionPassword == null || connectionPassword.equals(""))) {
@@ -334,7 +277,7 @@
dbConnection = DriverManager.getConnection(connectionURL,
connectionName, connectionPassword);
}
- JDBCstarted=true;
+ JDBCStarted=true;
if (dbConnection == null || dbConnection.isClosed()) {
log(sm.getString("jdbcRealm.checkConnectionDBReOpenFail"));
return false;
@@ -343,6 +286,7 @@
return true;
} catch (SQLException ex) {
log(sm.getString("jdbcRealm.checkConnectionSQLException"), ex);
+ close();
return false;
}
catch (ClassNotFoundException ex) {
@@ -361,11 +305,7 @@
if (!checkConnection())
return null;
if (preparedRoles == null) {
- String sql = "SELECT " + roleNameCol + " FROM " + userRoleTable
- + " WHERE " + userNameCol + " = ?";
- if (debug >= 1)
- log("JDBCRealm.roles: " + sql);
- preparedRoles = dbConnection.prepareStatement(sql);
+ preparedRoles=getPreparedRoles(dbConnection);
}
preparedRoles.clearParameters();
preparedRoles.setString(1, username);
@@ -389,148 +329,69 @@
// Set the connection to null.
// Next time we will try to get a new connection.
log(sm.getString("jdbcRealm.getUserRolesSQLException", username));
- if (preparedRoles != null) {
- try {
- preparedRoles.close();
- } catch (Throwable t) {
- ;
- }
- preparedRoles = null;
- }
- if (dbConnection != null) {
- try {
- dbConnection.close();
- } catch (Throwable t) {
- ;
- }
- dbConnection = null;
- }
+ close();
}
return null;
}
- // -------------------- Tomcat hooks --------------------
- public void contextInit(Context ctx) throws org.apache.tomcat.core.TomcatException {
- super.contextInit(ctx);
- init(ctx.getContextManager());
- // Validate and update our current component state
- }
+ // Nothing - except carry on the class name information
+ public static class JdbcPrincipal extends SimplePrincipal {
+ private String name;
- public void contextShutdown(Context ctx) throws org.apache.tomcat.core.TomcatException {
- shutdown();
+ JdbcPrincipal(String name) {
+ super(name);
+ }
+
}
- public void shutdown() throws org.apache.tomcat.core.TomcatException {
- // Validate and update our current component state
- if (started) {
- started = false;
+ private void close() {
+ if (preparedRoles != null) {
try {
- if (dbConnection != null && !dbConnection.isClosed())
- dbConnection.close();
- } catch (SQLException ex) {
- log("dbConnection.close Exception!!!", ex);
+ preparedRoles.close();
+ } catch (Throwable t) {
+ ;
}
+ preparedRoles = null;
}
- }
-
- /** Authenticate hook implementation */
-
- public int authenticate(Request req, Response response) {
- String user = (String)req.getNote(userNote);
- String password = (String)req.getNote(passwordNote);
- if (user == null) return DECLINED;
- if (checkPassword(user, password)) {
- if (debug > 0) log("Auth ok, user=" + user);
- Context ctx = req.getContext();
- if (ctx != null)
- req.setAuthType(ctx.getAuthMethod());
- if (user != null) {
- req.setRemoteUser(user);
- req.setUserPrincipal( new JdbcPrincipal( user ));
- String userRoles[] = getUserRoles(user);
- req.setUserRoles(userRoles);
- return OK;
+ if (preparedAuthenticate != null) {
+ try {
+ preparedAuthenticate.close();
+ } catch (Throwable t) {
+ ;
}
+ preparedAuthenticate = null;
}
- return DECLINED;
- }
-
- /**
- * Digest password using the algorithm especificied and
- * convert the result to a corresponding hex string.
- * If exception, the plain credentials string is returned
- * @param credentials Password or other credentials to use in authenticating this username
- * @param algorithm Algorithm used to do th digest
- */
- public final static String digest(String credentials, String algorithm) {
- try {
- // Obtain a new message digest with MD5 encryption
- MessageDigest md = (MessageDigest)MessageDigest.getInstance(algorithm).clone();
- // encode the credentials
- md.update(credentials.getBytes());
- // obtain the byte array from the digest
- byte[] dig = md.digest();
- // convert the byte array to hex string
- // Base64 enc=new Base64();
- // return new String(enc.encode(HexUtils.convert(dig).getBytes()));
- return HexUtils.convert(dig);
- } catch (Exception ex) {
- ex.printStackTrace();
- return credentials;
- }
- }
-
- /**
- * JDBCRealm can be used as a standalone tool for offline password digest
- * @param args
- */
- public static void main(String args[]) {
- if (args.length >= 2) {
- if (args[0].equalsIgnoreCase("-a")) {
- for (int i = 2; i < args.length; i++) {
- System.out.print(args[i] + ":");
- System.out.println(digest(args[i], args[1]));
- }
+ if (dbConnection != null) {
+ try {
+ dbConnection.close();
+ } catch (Throwable t) {
+ ;
}
+ dbConnection = null;
}
}
- /** Called when the ContextManager is started */
- public void engineInit(ContextManager cm) throws TomcatException {
- super.engineInit(cm);
- init(cm);
+ protected void ContextShutdown(Context ctx) throws TomcatException {
+ if (started && JDBCStarted) close();
}
- void init(ContextManager cm) {
+ protected void ContextInit(Context ctx) throws TomcatException {
if (!started) {
- started = true;
- // set-up a per/container note for maps
- try {
- // XXX make the name a "global" static - after everything is stable!
- reqRolesNote = cm.getNoteId(ContextManager.REQUEST_NOTE, "required.roles");
- userNote = cm.getNoteId(ContextManager.REQUEST_NOTE, "credentials.user");
- passwordNote = cm.getNoteId(ContextManager.REQUEST_NOTE, "credentials.password");
- if (connectOnInit && !checkConnection())
- throw new RuntimeException("JDBCRealm cannot be started");
- }
- catch (TomcatException ex) {
- log("setting up note for " + cm, ex);
- throw new RuntimeException("Invalid state ");
+ if (connectOnInit && !checkConnection()) {
+ throw new RuntimeException("JDBCRealm cannot be started");
}
+ started=true;
}
}
- public void engineShutdown(ContextManager cm) throws TomcatException {
- shutdown();
+ /**
+ * getPrincipal
+ * @param username
+ * @return java.security.Principal
+ */
+ protected Principal getPrincipal(String username) {
+ return new JdbcPrincipal( username );
}
- // Nothing - except cary on the class name information
- public static class JdbcPrincipal extends SimplePrincipal {
- private String name;
-
- JdbcPrincipal(String name) {
- super(name);
- }
- }
}
1.1 jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/RealmBase.java
Index: RealmBase.java
===================================================================
/*
* $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/aaa/RealmBase.java,v 1.1 2001/07/14 03:20:37 nacho Exp $
* $Revision: 1.1 $
* $Date: 2001/07/14 03:20:37 $
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.tomcat.modules.aaa;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.core.*;
import java.security.MessageDigest;
import java.security.Principal;
/*
* Abstract Base class for Realms.
* This class is intented to be a helper for defining Realms, it contains basic
* utils for Digesting passwords, and create associated notes.
* There are 3 abstract methods in this class, every Realm that inherits from
* RealmBase needs to define them to make a basic working Realm..they are:
*
* protected abstract String getCredentials(String username);
* protected abstract String[] getUserRoles(String username);
* protected abstract Principal getPrincipal(String username);
*
* Defining this methods and if needed contextInit and contextShutdown from
* BaseInterceptor are the only methods a Realm Writer needs
* to take into account to construct a functional Realm for Tomcat 3.3
*
* A Complex Realm that need more control over the auth process can already
* inherit directly from BaseInterceptor.
*
*/
public abstract class RealmBase extends BaseInterceptor {
int reqRolesNote=-1;
int userNote=-1;
int passwordNote=-1;
/** The string manager for this package. */
protected static StringManager sm = StringManager.getManager("org.apache.tomcat.resources");
/**
* Digest algorithm used in passwords thit is same values accepted by MessageDigest for algorithm
* plus "No" ( no encode ) that is the default
*/
protected String digest = "No";
/**
* Gets the digest algorithm used for credentials in the database
* could be the same that MessageDigest accepts vor algorithm and "No" that
* is the Default
* @return
*/
public String getDigest() {
return digest;
}
/**
* Sets the digest algorithm used for credentials in the database
* could be the same that MessageDigest accepts vor algorithm and "No"
* that is the Default
* @param algorithm the Encode type
*/
public void setDigest(String algorithm) {
digest = algorithm;
}
/**
* Digest password using the algorithm especificied and
* convert the result to a corresponding hex string.
* If exception, the plain credentials string is returned
* @param credentials Password or other credentials to use in authenticating this username
* @param algorithm Algorithm used to do th digest
*/
public static final String digest(String credentials,String algorithm ) {
try {
// Obtain a new message digest with MD5 encryption
MessageDigest md = (MessageDigest)MessageDigest.getInstance(algorithm).clone();
// encode the credentials
md.update(credentials.getBytes());
// obtain the byte array from the digest
byte[] dig = md.digest();
// convert the byte array to hex string
// Base64 enc=new Base64();
// return new String(enc.encode(HexUtils.convert(dig).getBytes()));
return org.apache.tomcat.util.buf.HexUtils.convert(dig);
} catch (Exception ex) {
ex.printStackTrace();
return credentials;
}
}
/**
* RealmBase can be used as a standalone tool for offline password digest
* @param args
*/
public static void main(String[] args) {
if (args.length >= 2) {
if (args[0].equalsIgnoreCase("-a")) {
for (int i = 2; i < args.length; i++) {
System.out.print(args[i] + ":");
System.out.println(digest(args[i], args[1]));
}
}
}
}
protected abstract String getCredentials(String username);
protected abstract String[] getUserRoles(String username);
protected abstract Principal getPrincipal(String username);
String digest(String credentials) {
if( digest.equals("") || digest.equalsIgnoreCase("No")){
return credentials;
} else {
return digest(credentials,digest);
}
}
public void engineInit( ContextManager cm )
throws TomcatException
{
reqRolesNote = cm.getNoteId( ContextManager.REQUEST_NOTE,
"required.roles");
userNote=cm.getNoteId( ContextManager.REQUEST_NOTE,
"credentials.user");
passwordNote=cm.getNoteId( ContextManager.REQUEST_NOTE,
"credentials.password");
}
public int authenticate(Request req, Response response) {
String user = (String)req.getNote(userNote);
String password = (String)req.getNote(passwordNote);
if (user == null) return DECLINED;
if (checkPassword(user, password)) {
if (debug > 0) log("Auth ok, user=" + user);
Context ctx = req.getContext();
if (ctx != null)
req.setAuthType(ctx.getAuthMethod());
if (user != null) {
req.setRemoteUser(user);
req.setUserPrincipal( getPrincipal( user ));
String userRoles[] = getUserRoles(user);
req.setUserRoles(userRoles);
return OK;
}
}
return DECLINED;
}
private boolean checkPassword(String username,String credentials) {
// Create the authentication search prepared statement if necessary
// Perform the authentication search
if (digest(credentials).equals(getCredentials(username))) {
if (debug >= 2)
log(sm.getString("jdbcRealm.authenticateSuccess", username));
return true;
}
if (debug >= 2)
log(sm.getString("jdbcRealm.authenticateFailure", username));
return false;
}
}