Hi all,
A previous developer had set up CAS 4.x with a custom authentication handler for our application environment. Please see the code for the handler and deployerConfigContext.xml:
deployerConfigContext.xml:
<util:map id="authenticationHandlersResolvers">
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</util:map>
<util:list id="authenticationMetadataPopulators">
<ref bean="successfulHandlerMetaDataPopulator" />
<ref bean="rememberMeAuthenticationMetaDataPopulator" />
</util:list>
<bean id="attributeRepository" class="org.jasig.services.persondir.support.NamedStubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" />
<alias name="acceptUsersAuthenticationHandler" alias="primaryAuthenticationHandler" />
<alias name="personDirectoryPrincipalResolver" alias="primaryPrincipalResolver" />
<util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
<entry>
<key><value>memberOf</value></key>
<list>
<value>faculty</value>
<value>staff</value>
<value>org</value>
</list>
</entry>
</util:map>
<alias name="serviceThemeResolver" alias="themeResolver" />
<alias name="jsonServiceRegistryDao" alias="serviceRegistryDao" />
<alias name="ehcacheTicketRegistry" alias="ticketRegistry" />
<alias name="ticketGrantingTicketExpirationPolicy" alias="grantingTicketExpirationPolicy" />
<alias name="multiTimeUseOrTimeoutExpirationPolicy" alias="serviceTicketExpirationPolicy" />
<alias name="anyAuthenticationPolicy" alias="authenticationPolicy" />
<alias name="acceptAnyAuthenticationPolicyFactory" alias="authenticationPolicyFactory" />
<bean id="auditTrailManager"
class="org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager"
p:entrySeparator="${cas.audit.singleline.separator:|}"
p:useSingleLine="${cas.audit.singleline:false}"/>
<alias name="neverThrottle" alias="authenticationThrottle" />
<util:list id="monitorsList">
<ref bean="memoryMonitor" />
<ref bean="sessionMonitor" />
</util:list>
<alias name="defaultPrincipalFactory" alias="principalFactory" />
<alias name="defaultAuthenticationTransactionManager" alias="authenticationTransactionManager" />
<alias name="defaultPrincipalElectionStrategy" alias="principalElectionStrategy" />
<alias name="tgcCipherExecutor" alias="defaultCookieCipherExecutor" />
<bean id="(customPasswordEncoder)" class="(classForPasswordEncoder)"/>
<bean id="DatabaseAuthenticationHandler" class="(classForCustomDatabaseHandler)">
<property name="principalFactory" ref="defaultPrincipalFactory"/>
<property name="passwordEncoder" ref="customPasswordEncoder"/>
<property name="dataSource">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="url" value="(ourSqlInstance);"/>
</bean>
</property>
<alias name="dataSource" alias="queryEncodeDatabaseDataSource" />
<alias name="DatabaseAuthenticationHandler" alias="primaryAuthenticationHandler" />
CustomDatabaseHandler:
package example.apps.cas.authentication;
import java.security.GeneralSecurityException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.authentication.BasicCredentialMetaData;
import org.jasig.cas.authentication.Credential;
import org.jasig.cas.authentication.DefaultHandlerResult;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.MessageDescriptor;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.DefaultPrincipalFactory;
import org.jasig.cas.authentication.principal.Principal;
import org.apache.commons.dbcp.BasicDataSource;
import example.apps.cas.dao.UserDao;
import example.apps.cas.model.UserModel;
public class DatabaseAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
private DefaultPrincipalFactory principalFactory = null;
private BasicDataSource dataSource = null;
@Override
public boolean supports(Credential credentials) {
return credentials != null && UsernamePasswordCredential.class.isAssignableFrom(credentials.getClass());
}
@Override
protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential credentials)
throws GeneralSecurityException, PreventedException {
String username = credentials.getUsername().trim();
String password = credentials.getPassword();
UserDao userDao = new UserDao();
BasicDataSource dataSource = this.getDataSource();
userDao.setDataSource(dataSource);
// Throw exception if username is blank
if (StringUtils.isEmpty(username)) {
throw new AccountNotFoundException("Username can not be blank.");
}
// Throw exception if password is blank
if (StringUtils.isEmpty(password)) {
throw new FailedLoginException(String.format("Password can not be blank for user %s.", username));
}
// Throw exception if unable to select password from database
UserModel user = new UserModel();
try {
user = userDao.getUser(username);
} catch (SQLException e) {
e.printStackTrace();
throw new PreventedException(String.format("Unable to retrieve password from database for user %s."), e);
}
// Throw exception if user account does not exist in database
if (user == null) {
throw new AccountNotFoundException(String.format("Unable to find account for user %s.", username));
}
// Throw exception if password cannot be encrypted
String encryptedPassword = this.getPasswordEncoder().encode(password);
if (encryptedPassword == null) {
throw new PreventedException(String.format("Unable to encrypt user password for user %s.", username),
new NullPointerException("Encoded password is null."));
}
// Throw exception if password do not match
if (!encryptedPassword.equals(user.getEncryptedPassword())) {
throw new FailedLoginException(String.format("Failed to authenticate password for user %s", username));
}
UsernamePasswordCredential handlerCredentials = new UsernamePasswordCredential();
handlerCredentials.setUsername(username);
handlerCredentials.setUsername(password);
return this.createHandlerResult(handlerCredentials, this.getPrincipalFactory().createPrincipal(username), null);
}
@Override
public String getName() {
return "DatabaseAuthenticationHandler";
}
public DefaultPrincipalFactory getPrincipalFactory() {
return principalFactory;
}
public void setPrincipalFactory(DefaultPrincipalFactory principalFactory) {
this.principalFactory = principalFactory;
}
public BasicDataSource getDataSource() {
return dataSource;
}
public void setDataSource(BasicDataSource dataSource) {
this.dataSource = dataSource;
}
1) Is there some documentation for individuals who are newer to Spring Framework, to help them create this configuration files?
2) I read that you can still use the deployerConfigContext.xml if need be. Is there some documentation on handling how you can get this to work with 5.x?
Apologies if there is any repeated questions, and thanks for your help!
Nick