Note | ||
---|---|---|
| ||
Work in progress... |
This page documents how to write a CAS3 AuthenticationHandler. If you already have a CAS2 PasswordHandler or TrustHandler, you can just use it in CAS3 without writing any new code and there is documentation intended specifically for explaining how to convert a CAS2 PasswordHandler to the CAS3 APIs. This page is intended to document CAS3 AuthenticationHandler implementation outside the context of CAS2.
...
Before we discuss actual APIs and code, it may be helpful to review the concepts of CAS authentication.
...
Credentials
Credentials are what someone presents to CAS as evidence on the basis of which they may be authenticated. A username, password pair is a Credentials, as is a cryptographic certificate, etc.
Principal
A Principal is an entity that is authenticated.
Core interfaces
The core interface to implement for your authentication-handling plugin is AuthenticationHandler.
Code Block | ||
---|---|---|
| ||
/**
* Validate Credentials support for AuthenticationManagerImpl.
*
* Determines that Credentials are valid. Password-based credentials may be
* tested against an external LDAP, Kerberos, JDBC source. Certificates may be
* checked against a list of CA's and do the usual chain validation.
* Implementations must be parameterized with their sources of information.
*
* Callers to this class should first call supports to determine if the
* AuthenticationHandler can authenticate the credentials provided.
*
* @version $Revision: 1.11 $ $Date: 2005/06/17 13:24:38 $
*/
public interface AuthenticationHandler {
/**
* Method to determine if the credentials supplied are valid.
*
* @param credentials The credentials to validate.
* @return true if valid, return false otherwise.
* @throws AuthenticationException An AuthenticationException can contain
* details about why a particular authentication request failed.
*/
boolean authenticate(Credentials credentials)
throws AuthenticationException;
/**
* Method to check if the handler knows how to handle the credentials
* provided. It may be a simple check of the Credentials class or something
* more complicated such as scanning the information contained in the
* Credentials object.
*
* @param credentials The credentials to check.
* @return true if the handler supports the Credentials, false othewrise.
*/
boolean supports(Credentials credentials);
}
|
You can code directly to this interface, or you can extend AbstractUsernamePasswordAuthenticationHandler if you're dealing with usernames and passwords.
Code Block | ||
---|---|---|
| ||
/** * Abstract class to override supports so that we don't need to duplicate the * check for UsernamePasswordCredentials. * * @version $Revision: 1.12 $ $Date: 2005/06/20 18:15:36 $ */ public abstract class AbstractUsernamePasswordAuthenticationHandler implements AuthenticationHandler, InitializingBean { /** * PasswordEncoder to be used by subclasses to encode passwords for * comparing against a resource. */ private PasswordEncoder passwordEncoder; /** Instance of logging for subclasses. */ private Log log = LogFactory.getLog(this.getClass()); /** * Method automatically handles conversion to UsernamePasswordCredentials * and delegates to abstract authenticateUsernamePasswordInternal so * subclasses do not need to cast. */ public final boolean authenticate(final Credentials credentials) throws AuthenticationException { return authenticateUsernamePasswordInternal((UsernamePasswordCredentials) credentials); } /** * Abstract convenience method that assumes the credentials passed in are a * subclass of UsernamePasswordCredentials. * * @param credentials the credentials representing the Username and Password * presented to CAS * @return true if the credentials are authentic, false otherwise. * @throws AuthenticationException if authenticity cannot be determined. */ protected abstract boolean authenticateUsernamePasswordInternal( final UsernamePasswordCredentials credentials) throws AuthenticationException; public final void afterPropertiesSet() throws Exception { if (this.passwordEncoder == null) { this.passwordEncoder = new PlainTextPasswordEncoder(); getLog().info( "No PasswordEncoder set. Using default: " + this.passwordEncoder.getClass().getName()); } afterPropertiesSetInternal(); } /** * Method designed to be overwritten subclasses that need to do additional * properties checking. * * @throws Exception if there is an error checking the properties. */ protected void afterPropertiesSetInternal() throws Exception { // this is designed to be overwritten } /** * Method to return the PasswordEncoder to be used to encode passwords. * * @return the PasswordEncoder associated with this class. */ public final PasswordEncoder getPasswordEncoder() { return this.passwordEncoder; } /** * Method to return the log instance in order for subclasses to have access * to the log object. * * @return the logging instance for this class. */ public final Log getLog() { return this.log; } /** * Sets the PasswordEncoder to be used with this class. * * @param passwordEncoder the PasswordEncoder to use when encoding * passwords. */ public final void setPasswordEncoder(final PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } /** * @return true if the credentials are not null and the credentials class is * assignable from UsernamePasswordCredentials. */ public final boolean supports(final Credentials credentials) { return credentials != null && UsernamePasswordCredentials.class.isAssignableFrom(credentials .getClass()); } } |