Revamped user login authentication to use a pluggable Authenticator

allowing applications to perform authentication as they see fit.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@727 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
shaper
2002-05-02 19:10:34 +00:00
parent b32956a893
commit bacb5b925a
5 changed files with 142 additions and 65 deletions
@@ -0,0 +1,32 @@
//
// $Id: AuthenticationFailedException.java,v 1.1 2002/05/02 19:10:34 shaper Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2002 Walter Korman
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.servlet.user;
/**
* Thrown when a user authentication attempt failed.
*/
public class AuthenticationFailedException extends Exception
{
public AuthenticationFailedException (String message)
{
super(message);
}
}
@@ -0,0 +1,49 @@
//
// $Id: Authenticator.java,v 1.1 2002/05/02 19:10:34 shaper Exp $
//
// samskivert library - useful routines for java programs
// Copyright (C) 2002 Walter Korman
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.servlet.user;
/**
* Provides a means for applications to use their own application-specific
* authentication schemes for validating a user by constructing their own
* authenticator and passing it to {@link UserManager#login}.
*/
public interface Authenticator
{
/**
* Checks whether the user should be authenticated based on the
* supplied user record and the specified user information. Throws an
* {@link AuthenticationFailedException} if the user fails to pass the
* authentication check for some reason.
*
* @param user the definitive user record loaded from the persistent
* repository against which the user-supplied data is to be checked.
* @param username the username supplied by the user.
* @param password the plaintext password supplied by the user.
* @param persist if true, the cookie will expire in one month, if
* false, the cookie will expire in 24 hours.
*
* @throws AuthenticationFailedException if the user failed to pass
* the authentication check.
*/
public void authenticateUser (
User user, String username, String password, boolean persist)
throws AuthenticationFailedException;
}
@@ -1,5 +1,5 @@
// //
// $Id: InvalidPasswordException.java,v 1.3 2001/08/12 01:34:31 mdb Exp $ // $Id: InvalidPasswordException.java,v 1.4 2002/05/02 19:10:34 shaper Exp $
// //
// samskivert library - useful routines for java programs // samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne // Copyright (C) 2001 Michael Bayne
@@ -23,7 +23,7 @@ package com.samskivert.servlet.user;
/** /**
* Thrown during authentication when an invalid password is supplied. * Thrown during authentication when an invalid password is supplied.
*/ */
public class InvalidPasswordException extends Exception public class InvalidPasswordException extends AuthenticationFailedException
{ {
public InvalidPasswordException (String message) public InvalidPasswordException (String message)
{ {
@@ -1,5 +1,5 @@
// //
// $Id: NoSuchUserException.java,v 1.3 2001/08/12 01:34:31 mdb Exp $ // $Id: NoSuchUserException.java,v 1.4 2002/05/02 19:10:34 shaper Exp $
// //
// samskivert library - useful routines for java programs // samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne // Copyright (C) 2001 Michael Bayne
@@ -23,7 +23,7 @@ package com.samskivert.servlet.user;
/** /**
* Thrown when a user cannot be located in the user database. * Thrown when a user cannot be located in the user database.
*/ */
public class NoSuchUserException extends Exception public class NoSuchUserException extends AuthenticationFailedException
{ {
public NoSuchUserException (String message) public NoSuchUserException (String message)
{ {
@@ -1,5 +1,5 @@
// //
// $Id: UserManager.java,v 1.12 2002/05/02 01:15:09 shaper Exp $ // $Id: UserManager.java,v 1.13 2002/05/02 19:10:34 shaper Exp $
// //
// samskivert library - useful routines for java programs // samskivert library - useful routines for java programs
// Copyright (C) 2001 Michael Bayne // Copyright (C) 2001 Michael Bayne
@@ -38,6 +38,48 @@ import com.samskivert.util.*;
*/ */
public class UserManager public class UserManager
{ {
/** An instance of the insecure authenticator for general-purpose use. */
public static final Authenticator AUTH_INSECURE =
new InsecureAuthenticator();
/** An instance of the password authenticator for general-purpose use. */
public static final Authenticator AUTH_PASSWORD =
new PasswordAuthenticator();
/**
* A totally insecure authenticator that authenticates any user.
* <em>Note:</em> Applications that make use of this authenticator
* should make sure the user has already been authenticated through
* some other means.
*/
public static class InsecureAuthenticator implements Authenticator
{
// documentation inherited
public void authenticateUser (
User user, String username, String password, boolean persist)
throws InvalidPasswordException
{
// don't care
}
}
/**
* An authenticator that requires that the user-supplied password
* match the actual user password.
*/
public static class PasswordAuthenticator implements Authenticator
{
// documentation inherited
public void authenticateUser (
User user, String username, String password, boolean persist)
throws AuthenticationFailedException
{
if (!user.passwordsMatch(password)) {
throw new InvalidPasswordException("error.invalid_password");
}
}
}
/** /**
* A user manager must be supplied with a {@link UserRepository} * A user manager must be supplied with a {@link UserRepository}
* through which it loads and saves user records. * through which it loads and saves user records.
@@ -148,40 +190,6 @@ public class UserManager
return user; return user;
} }
/**
* Authenticates the requester and initiates an authenticated session
* for them. <em>Note:</em> The caller should make sure the user has
* been authenticated through some other means before calling this
* method. An authenticated session involves their receiving a cookie
* that proves them to be authenticated and an entry in the session
* database being created that maps their information to their
* userid. If this call completes, the session was established and the
* proper cookies were set in the supplied response object. If some
* other error occurs, an exception will be thrown.
*
* @param username The username supplied by the user.
* @param persist If true, the cookie will expire in one month, if
* false, the cookie will expire in 24 hours.
* @param rsp the response in which the cookie is to be set.
*
* @return the user object of the authenticated user.
*/
public User login (String username, boolean persist,
HttpServletResponse rsp)
throws PersistenceException, NoSuchUserException
{
// load up the requested user
User user = _repository.loadUser(username);
if (user == null) {
throw new NoSuchUserException("error.no_such_user");
}
// generate a session and set the user's auth cookie
generateSession(user, persist, rsp);
return user;
}
/** /**
* Attempts to authenticate the requester and initiate an * Attempts to authenticate the requester and initiate an
* authenticated session for them. An authenticated session involves * authenticated session for them. An authenticated session involves
@@ -196,44 +204,25 @@ public class UserManager
* @param password The plaintext password supplied by the user. * @param password The plaintext password supplied by the user.
* @param persist If true, the cookie will expire in one month, if * @param persist If true, the cookie will expire in one month, if
* false, the cookie will expire in 24 hours. * false, the cookie will expire in 24 hours.
* @param rsp the response in which the cookie is to be set. * @param rsp The response in which the cookie is to be set.
* @param auth The authenticator used to check whether the user should
* be authenticated.
* *
* @return the user object of the authenticated user. * @return the user object of the authenticated user.
*/ */
public User login (String username, String password, boolean persist, public User login (String username, String password, boolean persist,
HttpServletResponse rsp) HttpServletResponse rsp, Authenticator auth)
throws PersistenceException, NoSuchUserException, throws PersistenceException, AuthenticationFailedException
InvalidPasswordException
{ {
// load up the requested user // load up the requested user
User user = _repository.loadUser(username); User user = _repository.loadUser(username);
if (user == null) { if (user == null) {
throw new NoSuchUserException("error.no_such_user"); throw new NoSuchUserException("error.no_such_user");
} }
if (!user.passwordsMatch(password)) {
throw new InvalidPasswordException("error.invalid_password");
}
// generate a session and set the user's auth cookie // run the user through the authentication gamut
generateSession(user, persist, rsp); auth.authenticateUser(user, username, password, persist);
return user;
}
/**
* Creates a new session for the specified user in the session
* database table and sets an authentication cookie in the supplied
* servlet response.
*
* @param user the user for whom a session is to be generated.
* @param persist If true, the cookie will expire in one month, if
* false, the cookie will expire in 24 hours.
* @param rsp the response in which the cookie is to be set.
*/
protected void generateSession (User user, boolean persist,
HttpServletResponse rsp)
throws PersistenceException
{
// generate a new session for this user // generate a new session for this user
String authcode = _repository.createNewSession(user, persist); String authcode = _repository.createNewSession(user, persist);
// stick it into a cookie for their browsing convenience // stick it into a cookie for their browsing convenience
@@ -245,6 +234,8 @@ public class UserManager
acookie.setMaxAge(24*60*60); // expire in 24 hours acookie.setMaxAge(24*60*60); // expire in 24 hours
} }
rsp.addCookie(acookie); rsp.addCookie(acookie);
return user;
} }
public void logout (HttpServletRequest req, HttpServletResponse rsp) public void logout (HttpServletRequest req, HttpServletResponse rsp)
@@ -277,11 +268,16 @@ public class UserManager
return null; return null;
} }
/** The user repository. */
protected UserRepository _repository; protected UserRepository _repository;
/** The interval id for the user session pruning interval. */
protected int _prunerid = -1; protected int _prunerid = -1;
/** The URL for the user login page. */
protected String _loginURL; protected String _loginURL;
/** The user authentication cookie name. */
protected static final String USERAUTH_COOKIE = "id_"; protected static final String USERAUTH_COOKIE = "id_";
/** Prune the session table every hour. */ /** Prune the session table every hour. */