CAS扩展——自定义查询数据库验证Handler
2012-11-13 11:04 飘扬的红领巾 阅读(7153) 评论(0) 编辑 收藏 举报问题由来
当我们使用CAS来搭建我们的单点登录系统时,由于CAS默认的登录认证是简单的用户名和密码相同即可通过认证,所以我们使用时经常需要通过查询数据库来认证用户名和密码。这便需要扩展CAS验证的Handler。
解决方案
首先找到CAS中很重要的一个配置文件,deployerConfigContext.xml,在X:\tomcat6\webapps\cas-server\WEB-INF下。找到
1: <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
这段是CAS默认的登录方式,即用户名和密码相同即可通过认证。我们现在需要改造它使之可以通过数据库查询的用户名和密码进行验证。
把上面的代码替换成:
1: <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
2: <property name="sql" value="select password from ucenter_user where username=? " />
3: <property name="dataSource" ref="dataSource" />
4: </bean>
CAS认证的逻辑是,先通过sql获取该用户名的密码,然后用该密码和用户名输入的密码进行比对,如果相同则通过认证。
dataSource是数据库配置:
1: <bean id="dataSource"
2: class="org.springframework.jdbc.datasource.DriverManagerDataSource">
3: <property name="driverClassName">
4: <value>oracle.jdbc.driver.OracleDriver</value>
5: </property>
6: <property name="url">
7: <value>jdbc:oracle:thin:@192.168.2.233:1521:splexsrc</value>
8: </property>
9: <property name="username">
10: <value>username</value>
11: </property>
12: <property name="password">
13: <value>passport</value>
14: </property>
15: </bean>
这样做已基本满足大部分业务的需求,但如果遇到一些特殊的需求,如要求登录支持用户名、邮箱地址、手机号码。你该怎么办呢?
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="sql" value="select password from ucenter_user where username=? or email=? or mobile=?" /> <property name="dataSource" ref="dataSource" /> </bean>
是这样吗?那我们看看QueryDatabaseAuthenticationHandler.java的源码:
1: public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
2:
3: @NotNull
4: private String sql;
5:
6: protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
7: final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
8: final String password = credentials.getPassword();
9: final String encryptedPassword = this.getPasswordEncoder().encode(
10: password);
11:
12: try {
13: final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
14: return dbPassword.equals(encryptedPassword);
15: } catch (final IncorrectResultSizeDataAccessException e) {
16: // this means the username was not found.
17: return false;
18: }
19: }
20:
21: /**
22: * @param sql The sql to set.
23: */
24: public void setSql(final String sql) {
25: this.sql = sql;
26: }
27: }
注意看line 13,QueryDatabaseAuthenticationHandler.java只支持一个参数,也就是说我们前面的写法是错误的,那么找到了原因,解决就很简单了。
自定义一个验证Handler,同样继承AbstractJdbcUsernamePasswordAuthenticationHandler.java.
1: public class UCQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {
2:
3: @NotNull
4: private String sql;
5:
6: protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
7: final String id = getPrincipalNameTransformer().transform(credentials.getUsername());
8: final String password = credentials.getPassword();
9: final String encryptedPassword = this.getPasswordEncoder().encode(
10: password);
11:
12: try {
13: final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, id,id,id);
14: return dbPassword.equals(encryptedPassword);
15: } catch (final IncorrectResultSizeDataAccessException e) {
16: // this means the username was not found.
17: return false;
18: }
19: }
20:
21: /**
22: * @param sql The sql to set.
23: */
24: public void setSql(final String sql) {
25: this.sql = sql;
26: }
27: }
注意line13,因为传入的sql=select password from ucenter_user where username=? or email=? or mobile=?。所以这里在查询时需要配置三个参数,均是用户名登陆填写的用户名(邮箱、手机号)。这样就满足了我们的需求,支持用户名、邮箱、手机号码登陆。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库