本期介绍一下CAS(Central Authentiction Service )中心认证服务,以Apereo CAS工程为核心讲解CAS是怎么解决商业级系统SSO(single sign-on)认证问题的。
目录
前言
一,SSO与SLO
二,CAS系统架构
三,CAS client
四 , CAS server
五,CAS protocol
在介绍CAS工作之前,要先从SSO的故事讲起。SSO(single sign-on)单点登陆和SLO(single logout)单点登出是分布式系统认证中一个经典问题。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.
首先要明白我们为什么要登陆系统?
当我们浏览器做访问请求服务器操作时,由于http协议是无状态的,并不会记录访问者的信息,这样服务器就分不清是哪个用户在发送请求,如果要携带客户端信息就要在http报文头上加用户信息字段,定制化的http就使用cookie来携带客户端用户的信息,带入到服务器中转化成服务器可处理的session去识别这个发送请求的用户到底是谁。
SSO存在的意义
如果在一个系统上,问题就很好理解,客户端通过cookie携带信息,服务器拿到请求的session提取用户信息往往就要开始做信息认证和权限审核了。然而在分布式系统场景,我们往往需要把不同模块拆分成不同系统来合理利用资源,降低系统的耦合性;或者不同的集群节点上允许不同的服务,当两个服务需要相互建立业务关系时就会面对一个问题,如何整合两个不同系统的认证系统使得用户只需要登录一次就可以访问所有相互信任的应用系统。
当然这个过程中用户其实是要完全无感的,人家使用你的系统总不能一直重复登陆登出系统吧。即使在内部也不能连续在多个系统中做信息定向认证,每个系统权限模型都不一样,可能需要大量的精力去调和各个权限系统的差别。所以我们的需求是独立设计一个权限认证系统来做全部系统的SSO,用户登陆后在服务器产生SSO session做认证和权限,成功登陆后生成一个TGT(ticket-granting ticket),并通过携带这个TGT token形成ST(service ticket)服务票据通过浏览器访问各个服务。当用户登出系统时SLO操作销毁生成的SSO session,登出后用户再去请求服务就会因为没有session的token而报错。
如何去实现一个商业级的单点登陆的认证系统,首先客户端方面,它需要支持众多的客户端协议(如CAS, SAML, OAuth, OpenID)来满足服务的扩展性;其次后端方面也需要支持众多的数据源(如LDAP, database, X.509, 2-factor)访问权限;同时它也要支持很多客户端的库(如Java,PHP,.Net)。当然你自己系统的权限模型要在你自己的权限系统上实现,如何接CAS系统和如何设计CAS系统是两回事。
那么Apereo CAS给了一个很好的答案去实现这样的认证系统:
fig.1 CAS 架构
可以看到CAS系统从上到下分别是用户的web层终端,处理web报文检查ST并路由的CAS client,处理session信息实现SSO功能的CAS server,以及后端存储权限信息的数据源。
CAS client做了两部分工作,一是通过各种协议和CAS server交互做SSO通讯,以Filter方式保护受保护的资源,对于访问受保护的资源的每个Web请求, 会分析该请求的Http请求中是否包含Server ticket,并在需要登录时,重定向到CAS Server,如果得到ST则直接定向到service。
另一方面打成软件包嵌入到用户的平台去使用。所以CAS client作为一个独立的项目被分成很多版,比如Java-cas-client,.NET-cas-client等。
CAS server是依赖于Spring Framework 来做用户的认证和权限请求处理的上层交互的,具体从client到server的交互如下图:
fig.2 CAS认证过程
而在用户的视角可能只是上图中的登陆框,在输入密码之后点击确定,CAS server会将信息与后端数据源交互认证,认证成功后在server生成与用户id对应的TGT并产生SSO session,用户请求通过携带TGT作为token包装成URL中的ST重定向到其他服务。如果在其他服务中发生错误或者退出,ST认证失败则默认重定向到登陆界面。所有与CAS的交互均采用SSL协议,确保,ST和TGC的安全性。
CAS protocol是定义在CAS client和server之间的基于HTTP的简单协议,现在有v1,v2,v3三个版本,CAS对应的URI表如下:
URI | Description |
---|---|
/login |
credential requestor / acceptor |
/logout |
destroy CAS session (logout) |
/validate |
service ticket validation |
/serviceValidate |
service ticket validation [CAS 2.0] |
/proxyValidate |
service/proxy ticket validation [CAS 2.0] |
/proxy |
proxy ticket service [CAS 2.0] |
/p3/serviceValidate |
service ticket validation [CAS 3.0] |
/p3/proxyValidate |
service/proxy ticket validation [CAS 3.0] |
协议对应登陆登出制定了很多参数,返回值和错误码,一个简单登陆的URI例子:
Simple login example:
https://server/cas/login?service=http%3A%2F%2Fwww.service.com
CAS 协议中还提供了Poxy(代理)模式,来解决更复杂的场景,比如代理服务器会加上代理认证票据字段做真正服务的SSO功能,具体关于CAS protocol proxy可见:https://blog.csdn.net/aaronsimon/article/details/82698776
参考:
1. https://github.com/apereo/cas
2. https://www.cnblogs.com/qingmuchuanqi48/p/10784667.html
3. https://www.apereo.org/projects/cas