CAS认证(3):验证用户信息
内部邀请码:C8E245J (不写邀请码,没有现金送)
国内私募机构九鼎控股打造,九鼎投资是在全国股份转让系统挂牌的公众公司,股票代码为430719,为“中国PE第一股”,市值超1000亿元。
这篇文章主要是对用户提交的用户名及密码等进行认证。该过程相对简单一些,但我们更多的是学习他的设计思路。
上一篇文章中,我们在authenticationViaFormAction 中的submit方法中TGT的生成是通过
String tempTGT= this.centralAuthenticationService.createTicketGrantingTicket(credentials);
方法来生成的。
在该方法中,参数credentials就是对用户提交的认证信息的封装,该对象主要就是简单的包含了用户名和密码等。
那我们进详细的看一看该方法中逻辑行为吧。
CentralAuthenticationService 接口是CAS中的核心接口,他定了CAS中核心的一些行为。
| createTicketGrantingTicket | 该方法主要是验证认证信息,生成TGT。 |
| grantServiceTicket | 该方法主要是生成ST |
| validateServiceTicket | 该方法主要是验证ST有效性。 |
| destroyTicketGrantingTicket | 该方法主要是销毁TGT |
| delegateTicketGrantingTicket | 该方法主要是代理票据的生成 |
可以看到,这些都是认证流程中的核心方法。
该接口的默认实现是 CentralAuthenticationServiceImpl 。我们先来看一下createTicketGrantingTicket方法
final Authenticationauthentication = this.authenticationManager.authenticate(credentials);
finalTicketGrantingTicket ticketGrantingTicket= new TicketGrantingTicketImpl(
this.ticketGrantingTicketUniqueTicketIdGenerator.getNewTicketId(TicketGrantingTicket.PREFIX),
authentication, this.ticketGrantingTicketExpirationPolicy);
this.ticketRegistry.addTicket(ticketGrantingTicket);
return ticketGrantingTicket.getId();
这里可以看到, 代码中先是通过调用this.authenticationManager.authenticate方法对credentials进行验证。并返回验证结果 authentication。在这个过程中,如果验证出现问题,是会抛出异常的。
然后通过构建一个TicketGrantingTicketImpl 对象来形成TGT对应信息。之前说过,TGT是以cookie的形式存在的。那是在客户端浏览器中存在形式。在server端测试存在一个ticketGrantTicket对象的。这一点同session与jessionid的关系非常像。生成的tgt存储在ticketRegistry中。然后返回TGT。这里先不对ticket的生成和管理进行讲解,后面会详细的说明,这里继续讲解认证的过程。
this.authenticationManager.authenticate(credentials);
我们要看一下该方法中的认证是怎么样的,首先要看一下这个类的结构是什么样的。CAS中对象的管理主要是通过spring的IOC实现的。关于认证的bean的配置主要是在deployConfigContext.xml中定义的。在该配置文件中
<bean id="authenticationManager" class="org.jasig.cas.authentication.AuthenticationManagerImpl">
<!--
credentialsToPrincipalResolvers主要是干两件事儿,
一是确认用户要授权,在默认配置中用的DefaultCredentialsToPrincipalResolver来填充角色
二是用这些分解器确认一个服务请求代理票据验证。这个需要明确的是代理登录流程
+-->
<property name="credentialsToPrincipalResolvers">
<list>
<!--
这个UsernamePasswordCredentials是支持用户名密码登录的解析器。如果采用其他的认证方式,那么需要替换解析器。这种解析器需要支持这种认证方式
+-->
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
<property name="attributeRepository">
<ref local="attributeRepository"/>
</property>
</bean> <!--这个类是表示支持http或是https协议的。他可以从URL获取凭证,并且可以根据回调地址获取服务地址。如果采用其他的通讯协议,可以进行相应的替换+-->
<bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver"/>
</list>
</property> <!-- 这里的list主要是维护了一个认证器链,用来对用户提交的认证信息进行认证。 +-->
<property name="authenticationHandlers">
<list>
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient"/>
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource"ref="dataSource" />
<property name="sql"value="select USER_PASSWORD fromt_sso_userinfo where USER_NAME=? " />
</bean>
</list>
</property>
</bean>
我们可以看到,在manager中,主要有两个list的属性:credentialsToPrincipalResolvers和authenticationHandlers
其中authenticationHandlers list主要是用来做认证用的。该list中所有的bean都需要实现AuthenticationHandler接口中的authenticate方法。用户提交认证请求之后,要满足该list中任意认证的条件才算是认证成功。每一个bean都可以配置自己的验证方式。所以,对于有多个认证方式的应用的时候,在这里自行组装认证条件就可以。
credentialsToPrincipalResolverslist属性主要是在验证成功之后,将用户属性提取出来。并传递到接入系统中。如果用户数据存储在存在多个数据源中,则在这里可以写多个属性提取器,分别将用户的属性提取出来,然后处理后传递给客户端。
下面我们就源码进行分析。查看AuthenticationManagerImpl.authenticateAndObtainPrincipal方法:
//通过验证器链对用户提供的认证信息进行认证
for (final AuthenticationHandlerauthenticationHandler : this.authenticationHandlers) {
if(authenticationHandler.supports(credentials)) {
foundSupported = true;
if(!authenticationHandler.authenticate(credentials)) {
。。。。。
} else {
。。。。。
authenticatedClass =authenticationHandler;
authenticated = true;
break;
}
}
}
这里可以看到,就是对authenticationHandlers 进行遍历,如果通过认证,则break。
foundSupported = false;
//认证成功之后,通过认证信息,提取出用户的完整信息
for (finalCredentialsToPrincipalResolver credentialsToPrincipalResolver : this.credentialsToPrincipalResolvers) {
if(credentialsToPrincipalResolver.supports(credentials)) {
final Principal principal =credentialsToPrincipalResolver
.resolvePrincipal(credentials);
foundSupported = true;
if (principal != null) {
return new Pair<AuthenticationHandler,Principal>(authenticatedClass,principal);
}
}
}
这里对credentialsToPrincipalResolvers进行解析,一旦获取到用户的属性,则构建了一个新的Pair对象,该对象中有认证的类和用户属性。
下面,我们就深入org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler看一下该类是如何对用户进行认证的。
这里,我对这个类简单看一下,credentials是对认证请求的简单封装。当然可以获取到用户名和密码。然后将密码进行加密之后,同数据库查询的结果进行比对。
final Stringusername = 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);
returndbPassword.equals(encryptedPassword);
} catch (finalIncorrectResultSizeDataAccessException e) {
// this means the username was notfound.
return false;
}
CAS中,对于数据库的操作主要都是使用spring的JdbcTemplate 来操作的。这里也不例外。
这里的业务逻辑比较简单。在回头看看这里的实现。他将能分离出来的组件全都独立出来。比如说密码加密算法。数据源,查询语句等。任何组件的更改不会对其他的组件产生影响。这就是面向对象的好处,这就是使用spring ioc的好处。
CAS认证(3):验证用户信息的更多相关文章
- CAS学习笔记(三)—— SERVER登录后用户信息的返回
一旦CAS SERVER验证成功后,我们就会跳转到客户端中去.跳转到客户端去后,大家想一想,客户端总要获取用户信息吧,不然客户端是怎么知道登录的是哪个用户.那么客户端要怎么获取用户信息呢? 其实验证成 ...
- cas 认证管理器
CAS-默认的认证管理器:AuthenticationManagerImpl <bean id="authenticationManager" class="org ...
- 【SSO单点系列】(4):CAS4.0 SERVER登录后用户信息的返回
接着上一篇,在上一篇中我们描述了怎么在CAS SERVER登录页上添加验证码,并进行登录.一旦CAS SERVER验证成功后,我们就会跳转到客户端中去.跳转到客户端去后,大家想一想,客户端总要获取用户 ...
- CAS3.5.2 Server登录后返回用户信息详细解决方案
单点登录(Single Sign-On, 简称SSO)是目前比较流行的服务于企业业务整合的解决方案之一,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.大家在使用时CA ...
- 从SpringMVC获取用户信息谈起
Github地址:https://github.com/andyslin/spring-ext 编译.运行环境:JDK 8 + Maven 3 + IDEA + Lombok spring-boot: ...
- .NET微信开发通过Access Token和OpenID获取用户信息
本文介绍如何获得微信公众平台关注用户的基本信息,包括昵称.头像.性别.国家.省份.城市.语言. 本文的方法将囊括订阅号和服务号以及自定义菜单各种场景,无论是否有高级接口权限,都有办法来获得用户基本信息 ...
- 我们一起学习WCF 第三篇头消息验证用户身份
前言:今天我主要写的是关于头消息的一个用处验证用户信息 下面我画一个图,可以先看图 第一步:我们先开始做用户请求代码 首先:创建一个可执行的上下文对象块并定义内部传输的通道 using (Operat ...
- CAS 单点登录4.24版本 登录调用其它系统并且返回客户端用其它的用户信息改造
1.登录调用其它系统.修改deployerConfigContext.xml <?xml version="1.0" encoding="UTF-8"?& ...
- 再谈Token认证,如何快速方便获取用户信息
前面我写了一篇<Token认证,如何快速方便获取用户信息>的文章,引起了各位读者的积极参与,除了文章中我提出的三种方式,各位读者大佬们也贡献了其他多种实现方式. 今天决定基于大家提供的思路 ...
随机推荐
- HDU 2045 不容易系列之(3)—— LELE的RPG难题(递推)
点我看题目 题意 : 中文题不解释. 思路 :先算了第3个第4个,算的时候发现只要在已经枚举出来的前边的状态中往后添加字母就行了,如果两个的都已经表示出来了,那第三个就可以在每个第二个后边加一个,在 ...
- Memcached总结二:Memcached环境安装设置以及连接memcache服务器
1 在Ubuntu上安装Memcached 要在Ubuntu上安装Memcached,打开终端,然后输入以下命令: $sudo apt-get update $sudo apt-get install ...
- 如何设置EditPlus的默认编码utf-8方式
最近在使用英文版的Editplus写代码的时候,发现中文字符在调试过程中都变成了乱码,发现是Editplus编码设置的问题,Editplus默认编码可能是ANSI,需要将其改成UTF-8.干脆给设置默 ...
- [杂题]CSUOJ1274Balls and Boxes
题目链接 题意:中文题 题意不多赘述 值得注意的是n<m 不必考虑n==m的情况 (m是盒子个数, n是每次选取的盒子个数, 不要弄反了!) 这题一看就是同余方程 每次选取n个盒子放球 也就是说 ...
- 去除Coding4Fun中MessagePrompt的边框(Border)
在App.xaml文件中添加 xmlns:c4f="clr-namespace:Coding4Fun.Toolkit.Controls;assembly=Coding4Fun.Toolkit ...
- 很受欢迎的Linux笔记(短小精悍)
http://blog.csdn.net/xsl1990/article/details/8274028 如何知道所使用的LINUX是哪个发行版? lsb_release -a 查找某个文件的另类方法 ...
- 存储过程中“Select Top 变量”的问题如何解决
在SqlServer2005中,可以这样: DECLARE @p int SELECT TOP (@p) * FROM 表名 在SqlServer2000中,不支持以上方法,可以这样: DECLARE ...
- [LOJ 1008] Fibsieve`s Fantabulous Birthday
A - Fibsieve`s Fantabulous Birthday Time Limit:500MS Memory Limit:32768KB 64bit IO Format:%l ...
- 发布网站,报Access to the path is denied的解决办法
错误: Server Error in '/' Application.---------------------------------------------------------------- ...
- 如何使用eclipse进行嵌入式Linux的开发
如何使用eclipse进行嵌入式Linux的开发 作者:曾宏安,华清远见嵌入式学院高级讲师. 如何使用eclipse进行嵌入式Linux的开发 习惯了在windows环境下开发的程序员在转到Linux ...