SSO 原理浅谈SSO 是一个非常大的主题,我对这个主题有着深深的感受,自从广州UserGroup 的论坛成立以来,无数网友都在尝试使用开源的CAS ,Kerberos 也提供另外一种方式的SSO ,即基于Windows 域的SSO ,还有就是从2005 年开始一直兴旺不衰的SAML 。
如果将这些免费的SSO 解决方案与商业的Tivoli 或Siteminder 或RSA Secure SSO 产品做对比,差距是存在的。
毕竟,商业产品的安全性和用户体验都是无与伦比的,我们现在提到的SSO ,仅仅是Web SSO ,即Web-SSO 是体现在客户端;另外一种SSO 是桌面SSO ,例如,只需要作为Administrator 登录一次windows 2000 ,我便能够在使用MSN/QQ 的时候免去登录的环节( 注意,这不是用客户端软件的密码记忆功能) ,是一种代理用户输入密码的功能。
因此,桌面SSO 是体现在OS 级别上。
今天,当我们提起SSO 的时候,我们通常是指Web SSO ,它的主要特点是,SSO 应用之间走Web 协议( 如HTTP/SSL) ,并且SSO 都只有一个登录入口。
简单的SSO 的体系中,会有下面三种角色:1 ,User (多个)2 ,Web 应用(多个)3 ,SSO 认证中心(1 个)虽然SSO 实现模式千奇百怪,但万变不离其宗:●Web 应用不处理User 的登录,否则就是多点登陆了,所有的登录都在SSO 认证中心进行。
●SSO 认证中心通过一些方法来告诉Web 应用当前访问用户究竟是不是张三/李四。
●SSO 认证中心和所有的Web 应用建立一种信任关系,SSO 认证中心对用户身份正确性的判断会通过某种方法告之Web 应用,而且判断结果必须被Web 应用信任。
2. CAS的基本原理CAS(Central Authentication Service) 是Yale 大学发起的一个开源项目,据统计,大概每10 个采用开源构建Web SSO 的Java 项目,就有8 个使用CAS 。
对这些统计,我虽然不以为然,但有一点可以肯定的是,CAS 是我认为最简单实效,而且足够安全的SSO 选择。
本节主要分析CAS 的安全性,以及为什么CAS 被这样设计,带着少许密码学的基础知识,我希望有助于读者对CAS 的协议有更深层次的理解。
2.1 CAS 的结构体系从结构体系看,CAS 包含两部分:●CAS ServerCAS Server 负责完成对用户的认证工作,CAS Server 需要独立部署,有不止一种CAS Server 的实现,Yale CAS Server 和ESUP CAS Server 都是很不错的选择。
CAS Server 会处理用户名/ 密码等凭证(Credentials) ,它可能会到数据库检索一条用户帐号信息,也可能在XML 文件中检索用户密码,对这种方式,CAS 均提供一种灵活但同一的接口/ 实现分离的方式,CAS 究竟是用何种认证方式,跟CAS 协议是分离的,也就是,这个认证的实现细节可以自己定制和扩展。
CAS ClientCAS Client 负责部署在客户端(注意,我是指Web 应用),原则上,CAS Client 的部署意味着,当有对本地Web 应用的受保护资源的访问请求,并且需要对请求方进行身份认证,Web 应用不再接受任何的用户名密码等类似的Credentials ,而是重定向到CAS Server 进行认证。
目前,CAS Client 支持(某些在完善中)非常多的客户端,包括Java 、.Net 、ISAPI 、Php 、Perl 、uPortal 、Acegi 、Ruby 、VBScript 等客户端,几乎可以这样说,CAS 协议能够适合任何语言编写的客户端应用。
2.2 CAS 协议剖析协议就像剖析设计模式,有些时候,协议让人摸不着头脑。
CAS 的代理模式要相对复杂一些,它引入了一些新的概念,我希望能够在这里描述一下其原理,有助于读者在配置和调试CAS SSO 有更清晰的思路。
如果没记错,CAS 协议应该是由Drew Mazurek负责可开发的,从CAS v1 到现在的CAS v3 ,整个协议的基础思想都是基于Kerberos 的票据方式。
CAS v1 非常原始,传送一个用户名居然是”yes\ndavid.turing” 的方式,CAS v2 开始使用了XML 规范,大大增强了可扩展性,CAS v3 开始使用AOP 技术,让Spring 爱好者可以轻松配置CAS Server 到现有的应用环境中。
CAS 是通过TGT(Ticket Granting Ticket) 来获取ST(Service Ticket) ,通过ST 来访问服务,而CAS 也有对应TGT ,ST 的实体,而且他们在保护TGT 的方法上虽然有所区别,但是,最终都可以实现这样一个目的——免去多次登录的麻烦。
下面,我们看看CAS 的基本协议框架:2.1.1 基础协议CAS 基础模式上图是一个最基础的CAS 协议,CAS Client 以Filter 方式保护Web 应用的受保护资源,过滤从客户端过来的每一个Web 请求,同时,CAS Client 会分析HTTP 请求中是否包请求Service Ticket( 上图中的Ticket) ,如果没有,则说明该用户是没有经过认证的,于是,CAS Client 会重定向用户请求到CAS Server (Step 2 )。
Step 3 是用户认证过程,如果用户提供了正确的Credentials ,CAS Server 会产生一个随机的Service Ticket ,然后,缓存该Ticket ,并且重定向用户到CAS Client (附带刚才产生的Service Ticket ),Service Ticket 是不可以伪造的,最后,Step 5 和Step6 是CAS Client 和CAS Server 之间完成了一个对用户的身份核实,用Ticket 查到Username ,因为Ticket 是CAS Server 产生的,因此,所以CAS Server 的判断是毋庸置疑的。
该协议完成了一个很简单的任务,就是User(david.turing) 打开IE ,直接访问helloservice 应用,它被立即重定向到CAS Server 进行认证,User 可能感觉到浏览器在helloservcie 和casserver 之间重定向,但User 是看不到,CAS Client 和CAS Server 相互间的Service Ticket 核实(Validation) 过程。
当CAS Server 告知CAS Client 用户Service Ticket 对应确凿身份,CAS Client 才会对当前Request 的用户进行服务。
2.2.2 CAS 如何实现SSO当我们的Web 时代还处于初级阶段的时候,SSO 是通过共享cookies 来实现,比如,下面三个域名要做SSO :如果通过CAS 来集成这三个应用,那么,这三个域名都要做一些域名映射,因为是同一个域,所以每个站点都能够共享基于 的cookies 。
这种方法原始,不灵活而且有不少安全隐患,已经被抛弃了。
CAS 可以很简单的实现跨域的SSO ,因为,单点被控制在CAS Server ,用户最有价值的TGC-Cookie 只是跟CAS Server 相关,CAS Server 就只有一个,因此,解决了cookies 不能跨域的问题。
回到CAS 的基础协议图,当Step3 完成之后,CAS Server 会向User 发送一个Ticket granting cookie (TGC) 给User 的浏览器,这个Cookie 就类似Kerberos 的TGT ,下次当用户被Helloservice2 重定向到CAS Server 的时候,CAS Server 会主动Get 到这个TGC cookie(吴晨辉注:这里的说法是错误的,server不可能可以主动要求IE提交cookies,在这里实际上这个cookie并不是颁发给应用服务器的,而是颁发给CAS服务器的,因此,如果CAS服务器能够得到这个cookie,而且这个cookie是一个内存cookie,则说明当前用户已经在CAS登录了。
),然后做下面的事情:1,如果User 的持有TGC 且其还没失效,那么就走基础协议图的Step4 ,达到了SSO 的效果。
2,如果TGC 失效,那么用户还是要重新认证( 走基础协议图的Step3) 。
2.2.2 CAS 的代理模式模式1 已经能够满足大部分简单的SSO 应用,现在,我们探讨一种更复杂的情况,即用户访问helloservice ,helloservice 又依赖于helloservice2 来获取一些信息,如同:User → helloservice → helloservice2这种情况下,假设helloservice2 也是需要对User 进行身份验证才能访问,那么,为了不影响用户体验(过多的重定向导致User 的IE 窗口不停地闪动) ,CAS 引入了一种Proxy 认证机制,即CAS Client 可以代理用户去访问其它Web 应用。
代理的前提是需要CAS Client 拥有用户的身份信息( 类似凭据) 。
与其说之前我们提到的TGC 是用户持有对自己身份信息的一种凭据,则这里的PGT 就是CAS Client 端持有的对用户身份信息的一种凭据。
凭借TGC ,User 可以免去输入密码以获取访问其它服务的Service Ticket ,所以,这里,凭借PGT ,Web 应用可以代理用户去实现后端的认证,而无需前端用户的参与。
如下面的CAS Proxy 图所示,CAS Client 在基础协议之上,提供了一个额外的PGT URL 给CAS Server, 于是,CAS Server 可以通过PGT URL 提供一个PGT 给CAS Client 。
初学者可能会对上图的PGT URL 感到迷惑,或者会问,为什么要这么麻烦,要通过一个额外的URL( 而且是SSL 的入口) 去传递PGT ?如果直接在Step 6 返回,则连用来做对应关系的PGTIOU 都可以省掉。
PGTIOU 设计是从安全性考虑的,非常必要,CAS 协议安全性问题我会在后面一节介绍。
于是,CAS Client 拿到了PGT( PGTIOU-85…..ti2td ) ,这个PGT 跟TGC 同样地关键,CAS Client 可以通过PGT 向后端Web 应用进行认证。
如下图所示,Proxy 认证与普通的认证其实差别不大,Step1, 2 与基础模式的Step 1,2 几乎一样,唯一不同的是,Proxy 模式用的是PGT 而不是TGC ,是Proxy Ticket (PT )而不是Service Ticket 。