1. CAS 单点登录原理解析
CAS是耶鲁大学发起的一个开源单点登录项目,也是用的最为广泛的开源项目。对于学习SSO有非常好的参考价值
单点登录(Single Sign On),简称为 SSO。多用于多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,最简单的单点登入实现可以完全基于 cookie ,通过往浏览器写带有登入信息的token来达到多点登入的目的,有兴趣的可以自己动手实现一个
先盗个图 :
从结构上看,分成了三部分:CAS Client,CAS Server,浏览器
CAS Client 与受保护的客户端应用部署在一起,以 Filter 方式保护 Web 应用的受保护资源,过滤从客户端过来的每一个Web请求
下面我将分为两部分(用户第一次登录验证和之后的登录验证)详细解析其登入原理
以上是第一次验证时基本流程
跨域的关键在于浏览器端的Cookie: TGC ,因为这个Cookie是设置在 SSO Server 端的,也就保证了统一票据和 Client 端域名无关。
cas 单点登录核心就是 单个cookie , N个session
在该协议中,所有与 CAS Server 的交互均采用 SSL 协议,以确保 ST 和 TGC 的安全性。
2. 认证与授权——单点登录协议盘点:OpenID vs OAuth2 vs SAML
认证 ( authenticate )和 授权 ( authorize )是两个容易被弄混的概念,尤其是只看英文。
由此可见,应用需要先认证用户身份,然后依据用户身份再授权,二者需要联合使用。
对于QQ或者微信这样的应用,用户在登录后会得到该账户的身份凭证。如果其他第三方应用信任并接受QQ或者微信的身份凭证,就可以直接使用该凭证通过第三方的 认证 而登录。登陆之后用户能有权限去做什么,这就是第三方应用根据自己政策而进行的 授权 。我们常遇到有网站在第一次使用QQ或微信账户登录之后需要绑定已用账户,就是因为虽然网站能够通过QQ账户的身份认证,但是对于这样的账户没有对应的授权。
同理,对于一个面向公司内部的服务环境,该公司可能有邮箱系统、网上办公系统、财务系统等等。如果这些系统都是独立的,那么公司的员工就需要每一个系统都分配一个账户,每个系统都需要单独登录。这样显然是低效而麻烦的,更好的解决方案应该是用户在内网中只需要登录一次,所有的子应用系统都能认证其身份,而免去重复登录,这样的方案就被称为单点登录( single sign-on, SSO )。
这样做的最明显的好处就是提高用户体验,用户只需要维护一对用户名和口令可以在公司内部畅通无阻。同时,因为是单点登录,所有的用户身份的都被 统一认证 ,也就是说用户的身份凭据(比如口令)只被保存在一处,其他子系统并不直接获得用户的口令等敏感信息,而是接收来自可信来源的身份证明。
单点登录和统一认证中主要的三个协议是 OpenID , OAuth , 金和 SAML ,被称为单点登录的三驾马车。这些协议已经有了各种语言版本的实现,本人也在其他文字做了详尽的介绍,这里专门对比下三种协议的异同。
OpenID是一种 认证 标准,互联网上有很多账户都是支持OpenID比如谷歌、雅虎、PayPal等等。
用户要使用OpenID就必须先在OpenID身份服务器(Identity Provider, IDP)获得OpenID 账号(比如Google账户)。用户可以使用OpenID账户来登录任何一个接受OpenID认证的服务应用(the relying party,RP,依赖方)。OpenID协议标准就是提供一个框架用来IDP和RP之间通信。
本质而言,用户的OpenID是一个为用户个人所拥有的特殊URL(比如 alice2016.openid.com),所以有些网站甚至会提供选项让用户自己去填写OpenID。
FaceBook曾经也是使用过OpenID的,后来转而开发FaceBook Connect.
OpenID的最新版本是OpenID Connect。具体协议信息请见这里 OpenID Connect 协议入门指南
准确来讲,OAuth2是一个授权的标准协议。也许会令人困惑,OAuth2是OpenID-Connect的基础,但是OpenID-Connect是认证协议(在OpenID-Connect中,ID-Token也被当做是一种资源)。
让我们回到OAuth2,OAuth2提供了一种代理访问机制,也就是说一个应用(可以被称为客户端)可以代替用户到资源服务器上获得属于用户的资源或是进行符合用户权限的操作 ,而用户不用将自己的用户名和口令等身份凭据分享给客户端。OAuth2是通过IDP给第三方应用颁发令牌(Token)来实现以上功能的,第三方应用通过使用令牌向资源服务换取对应的资源。
在Twitter的OAuth指导手册中说OAuth2是一种认证协议,实际上,这是基于授权的“伪认证”。
OAuth协议的认证过程可以类比为如下流程:Alice要外出一段时间,让自己的朋友Bob代为照顾她的房子,所以Alice把自己房子的钥匙交给了Bob,而Bob也就可以任意的进入房子。这里的钥匙就是一种授权的体现——Alice授权Bob进入房子。在这里例子中,房子的所有者Alice就是用户,Bob是客户端,而门锁就是IDP,房子是资源服务器。
如果假设房子钥匙的拥有者就是房子的所有者,那么这个授权的过程也是一种 伪认证 ,之所以加一个伪字,是因为 这个假设并不是总是成立的,比如Bob虽然有钥匙,但是并不是房子的所有者Alice。
更多OAuth的内容,请参见我之前的文章。 OAuth2.0 协议入门指南
SAML协议是三者中时间最长的协议,最初版本制定于2001年,并于2005年修改。作为一种安全性断言标记语言,SAML协议既可以用于认证也用于授权。
所谓的安全性断言,就是关于认证、授权以及用户属性(比如用用户的有效或者住址等信息)的声明集合,在SAML中,这些断言以XML的格式传输。
当要验证一个用户身份时,服务提供商(Service Provider, SP,即RP,应有依赖方)会向IDP发出SAML认证请求,该请求中会以XML格式说明认证方式的设置,比如希望IDP以何种方式验证用户;IDP在认证通过用户身份之后,会返回SAML请求响应,同样以XML格式返回断言表明用户身份和相关属性,此外SAML安全性断言信息必须要使用数字签名以保证其完整性和不可抵赖性(没有强制要求对SAML断言加密);SP接收到SAML断言之后,验证其消息来源是否费受信任的IDP,验证通过之后解析XML获得认证信息。
除了断言,SAML还定义了如下概念:
更为详细的内容请见:
以下是三种协议的相关对比和总结,便于读者根据自己实际情形来选择下一步要继续去了解哪一种协议。
如果想进一步以上协议的具体,欢迎阅读我的其他文章:
3. CAS单点登录基本原理
一、几个概念
TGT(Ticket Grant Ticket):是cas服务端为用户签发的登录票据,封装了cookie和用户信息,有TGT代表用户已经登录过。
TGC(Ticket Granting Cookie):可以理解成TGT的cookie,cookie的值就是TGT的ID。
ST(service Ticket):cas服务端签发的访问某个服务的票据,server用TGT去签发ST
二、基本原理
现有webClient1、webClient2访问CASServer,分析流程:
1、首先:请求webClient1
1)、请求webClient1的request被CASAuthencationFilter拦截,将该请求的url作为sevice参数,重定向至cas/login;
2)、CAS检测到请求中没有TGC,跳转至自己的登录界面;
3)、登录验证通过,CASServer生成TGT和ST,并将TGT的id写到浏览器(TGC),将ST做为参数,重定向至webClient1。
4)、此时webClient1的CASAthencationFilter会通过,此时被TicketVaildationFilter拦截,这个过滤器发送httpClient请求去验证ST的正确性,server验证通过,将用户信息写到wenClient1的session中。
现在SSO会话就建立起来了。
2、然后,再次访问webClient1,会直接去自己的session中拿取用户信息,不需要服务端验证。
3、浏览器未关闭情况下访问webClient2
1)、webClient2检测自己的session中没有用户信息,request被CASAuthencationFilter拦截,将该请求的url作为sevice参数,重定向至cas/login;
2)、此时请求中会有TGC,CASServer会根据TGC查找到TGT,然后用TGT去签发ST
接下来就是1.4中的步骤了。
4. CAS单点登录原理分析(一)
一,业务分析
在分布式系统架构中,假设把上述的三个子系统部署在三个不同的服务器上。前提是用户登录之后才能访问这些子系统。那么使用传统方式,可能会存在这样的问题:
1.当访问用户中心,需要用户登录帐号
2.当访问购物车,还需要用户登录帐号
3.当访问商品结算,又一次需要用户登录帐号
访问每一个子系统都需要用户登录帐号,这样的体验对于用户来说是极差。而使用单点登录就可以很好地解决上述的问题。
二,单点登录
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
我们目前的系统存在诸多子系统,而这些子系统是分别部署在不同的服务器中,那么使用传统方式的 session 是无法解决的,我们需要使用相关的单点登录技术来解决。
第一步 :用户访问应用系统1。过滤器判断用户是否登录,没有登录,则重定向(302)到认证系统去进行认证操作。
第二步 :重定向到认证系统,显示登录界面,用户输入用户名密码。认证系统将用户登录的信息记录到服务器的session中。
第三步 :认证系统给浏览器发送一个特殊的凭证ticket,浏览器将凭证交给应用系统1,应用系统1则拿着浏览器交给他的凭证ticket去认证系统验证凭证ticket是否有效。凭证ticket若是有效,将用户信息保存到应用系统1的session中一份,并告知应用系统1,用户通过认证。
第四步 :用户通过认证,浏览器与网站之间进行正常的访问。
第五步 :当用户再次访问应用系统1,由于应用系统1的session中有用户信息,所以就不用经过认证系统认证,就可以直接访问应用系统1了。
第六步 :当用户再去访问其他应用系统时,浏览器会带着凭证ticket过去,其他应用系统到认证系统验证凭证,凭证ticket若是有效,将用户信息保存到其他应用系统的session中一份,并告知其他应用系统,用户通过认证。
第七步 :用户通过认证,浏览器与网站之间进行正常的访问。
第八步 :当用户再次访问其他应用系统,由于其他应用系统的session中有用户信息,所以就不用经过认证系统认证,就可以直接访问其他应用系统了。
三、Yelu大学研发的CAS(Central Authentication Server)
1.什么是CAS?
CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点:
【1】开源的企业级单点登录解决方案。
【2】CAS Server 为需要独立部署的 Web 应用。这个CAS框架已经提供
【3】CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。
从结构上看,CAS 包含两个部分: CAS Server 和 CAS Client。CAS Server 需要独立部署,主要负责对用户的认证工作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。下图是 CAS 最基本的协议过程:
2.CAS的详细登录流程
该图主要描述
1.第一次访问http://shopping.xiaogui.com
2.在登录状态下第二次访问http://shopping.xiaogui.com
3.在登录状态下第一次访问http://pay.xiaogui.com
下面对图中序号代表的操作进行说明
当用户第一次访问http://shopping.xiaogui.com
序号1: 用户请求http://shopping.xiaogui.com,会经过AuthenticationFilter认证过滤器(在cas client 的web.xml中配置)
主要作用:判断是否登录,如果没有登录则重定向到认证中心。
大概知道这个就行,CAS的具体实现会在以后的博客中写道
序号2: AuthenticationFilter发现用户没有登录,则返回浏览器重定向地址。
重定向的地址就是认证服务器CAS Server的地址,后面的参数是我们请求的客户端地址,这个参数目的就是为了认证成功以后,根据这个参数的地址重定向回请求的客户端
序号3: 浏览器根据响应回来的重定向地址,向cas.xiaogui.com认证系统发出请求
序号4: 认证系统cas.xiaogui.com接收请求,响应登陆页面
序号5: :用户登陆页面输入用户名密码,提交请求
序号6: :CAS Server 认证服务器接收用户名和密码,就行验证,验证逻辑CAS Server 已经实现,并响应给浏览器信息
这里的用户名,密码不需要关心,后续会讲到
图中1,2部分表示序号5 输入的用户名,密码,以及发出的请求。当认证服务器验证通过之后,根据请求参数service的值,进行重定向,其实就是回到了请求的客户端,同时会携带一个ticket令牌参数。同时会在Cookie中设置一个TGC,该cookie是网站认证系统cas.xiaogui.com的cookie,只有访问这个网站才会携带这个cookie过去。
*****注意:这个携带TGC的Cookie是实现CAS单点登录的关键所在!
Cookie中的TGC:向cookie中添加该值的目的是当下次访问cas.xiaogui.com认证系统时,浏览器将Cookie中的TGC携带到服务器,服务器根据这个TGC,查找与之对应的TGT。从而判断用户是否登录过了,是否需要展示登录页面。TGT与TGC的关系就像SESSION与Cookie中SESSIONID的关系。
TGT:Ticket Granted Ticket(俗称大令牌,或者说票根,他可以签发ST)
TGC:Ticket Granted Cookie(cookie中的value),存在Cookie中,根据他可以找到TGT。
ST:Service Ticket (小令牌),是TGT生成的,默认是用一次就生效了。也就是上面数字3处的ticket值。
序号7: 客户端拿到请求中的ticket信息,也就是图中1的位置
然后经过一个ticket过滤器Cas20ProxyReceivingTicketValidationFilter,去认证系统CAS Server判断ticket是否有效
这个过滤器的主要工作就是校验客户端传过来的ticket是否有效
CAS Client 客户端 shopping.xiaogui.com 中web.xml的配置
序号8: 向CAS Server认证系统发出验证ticket的请求,也就是图中2的位置,然后执行ticket验证
序号9: 通过校验之后,把用户信息保存到客户端的session中,并把客户端的SessionID设置在Cookie中,同时告知客户端ticket有效。当用户再次访问该客户端,就可以根据Cookie 中的SessionID找到客户端的Session,获取用户信息,就不用再次进行验证了。也就是图中响应给浏览器的部分。
序号10: shopping.xiaogui.com客户端接收到cas-server的返回,知道了用户已经登录,ticket有效,告知浏览器可以进行访问。
至此,用户第一次访问流程结束。
当用户第二次访问http://shopping.xiaogui.com
序号11: 当用户第二次访问,仍然会经过AuthenticationFilter过滤器,但与第一次访问不同的是此时客户端session中已经存在用户的信息,浏览器中的Cookie会根据SessionID找到Session,获取用户信息,所以不需要进行验证,可以直接访问。
序号12: 客户端告知浏览器可以进行访问。
当用户第一次访问http://pay.xiaogui.com
序号13: 用户向pay.xiaogui.com CAS Client客户端发出请求
序号14: :pay.xiaogui.com接收到请求,发现第一次访问,于是给他一个重定向的地址,让他去找认证中心登录。
序号15: 浏览器根据上面响应的地址,发起重定向,因为之前访问过一次了,因此这次会携带上次返回的Cookie:TGC到认证中心。
序号16: 认证中心收到请求,发现TGC对应了一个TGT,于是用TGT签发一个ticket,并且返回给浏览器,让他重定向到pay.xiaogui.comCAS Client客户端。
序号17: 根据上面响应回来的地址,进行重定向到pay.xiaogui.comCAS Client客户端
序号18: pay.xiaogui.comCAS Client客户端带着ticket去认证中心验证是否有效。
序号19: 认证成功,把用户信息保存到客户端的session中,并把客户端的SessionID设置在Cookie中。当用户下次访问pay.xiaogui.comCAS Client客户端,直接登录,无需验证。
序号20: 告知浏览器可以进行访问
CAS单点登录的原理分析大致就是上述的这些,至于CAS单点登录的具体实现,将在下篇博客中写道。