一、CAS客户端配置
新建两个WEB工程,从cas-client-3.2.1\modules导入jar包
cas-client-core-3.2.1.jar
commons-logging-1.1.jar
WEB工程的web.xml中需要添加的内容参看上篇文章中提到的咖啡兔的配置文章,再次不再赘述。
上面的初体验仅仅是简单的身份验证,实际应用中肯定是要读取数据库的数据,下面我们来进一步配置
CAS服务器怎么读取数据库的信息进行身份验证。
二、CAS结合数据库认证
1、找到并打开deployerConfigContext.xml
2、将下面的简单的验证配置注释掉
<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
3、添加如下配置
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource"></property>
<property name="sql" value="select password from user where username=?"></property>
</bean>
<!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<!-- 基本属性 url、user、password -->
<property name="url" value="jdbc:oracle:thin:@192.168.1.37:1521:orcl" />
<property name="username" value="orcl" />
<property name="password" value="orcl" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="3" />
<property name="minIdle" value="3" />
<property name="maxActive" value="6" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用) -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat" />
</bean>
4、将cas-server-3.5.1\modules\cas-server-support-jdbc-3.5.1.jar及BoneCP所需要的jar添加到工程中
使用数据库中存在的用户登录,登录web工程cas-test:
然后在访问web工程cas-test2,发现无需再跳转到登录页面,而是直接是工程的默认的访问页面
三、数据库数据源认证逻辑
关键代码
AbstractUsernamePasswordAuthenticationHandler.java
/**
* PasswordEncoder to be used by subclasses to encode passwords for
* comparing against a resource.
*/
@NotNull
private PasswordEncoder passwordEncoder = new PlainTextPasswordEncoder();
@NotNull
private PrincipalNameTransformer principalNameTransformer = new NoOpPrincipalNameTransformer();
/**
* Method automatically handles conversion to UsernamePasswordCredentials
* and delegates to abstract authenticateUsernamePasswordInternal so
* subclasses do not need to cast.
*/
protected final boolean doAuthentication(final Credentials credentials)
throws AuthenticationException {
return authenticateUsernamePasswordInternal((UsernamePasswordCredentials) credentials);
}
PlainTextPasswordEncoder.java
/**
* Default password encoder for the case where no password encoder is needed.
* Encoding results in the same password that was passed in.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.0
*/
public final class PlainTextPasswordEncoder implements PasswordEncoder {
public String encode(final String password) {
return password;
}
}
QueryDatabaseAuthenticationHandler.java
protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
final String password = credentials.getPassword();
final String encryptedPassword = this.getPasswordEncoder().encode(
password);
try {
final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
return dbPassword.equals(encryptedPassword);
} catch (final IncorrectResultSizeDataAccessException e) {
// this means the username was not found.
return false;
}
}
说明:
QueryDatabaseAuthenticationHandler:cas-server-support-jdbc提供的查询接口其中一个,QueryDatabaseAuthenticationHandler是通过配置一个 SQL 语句查出密码,与所给密码匹配。
如果需要使用密码加密,可以创建一个类实现 org.jasig.cas.authentication.handler.PasswordEncoder,然后在encode中加密用户输入的密码返回即可。如果需要在代码中获取用户名密码进行验证,可以创建一个类继承 org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler,重写authenticateUsernamePasswordInternal方法。