CAS实现SSO 单点登录

结构

CAS分为两部分,CAS Server和CAS Client

  • CAS Server用来负责用户的认证工作,就像是把第一次登录用户的一个标识存在这里,以便此用户在其他系统登录时验证其需不需要再次登录。
  • CAS Client就是我们自己的应用,需要接入CAS Server端。当用户访问我们的应用时,首先需要重定向到CAS Server端进行验证,要是原来登陆过,就免去登录,重定向到下游系统,否则进行用户名密码登陆操作。

 

术语

  • Ticket Granting ticket (TGT) :可以认为是CAS Server根据用户名密码生成的一张票,存在server端
  • Ticket-granting cookie (TGC) :其实就是一个cookie,存放用户身份信息,由server发给client端
  • Service ticket (ST) :由TGT生成的一次性票据,用于验证,只能用一次。相当于server发给client一张票,然后client拿着这是个票再来找server验证,看看是不是server签发的。

流程

  

假设我们现在有应用系统A、应用系统B、CAS认证系统

  • 1、第一次访问系统A时,没有票据(ST),也没有session,会重定向到CAS服务器,要求用户输入用户名和密码,之后CAS向浏览器写入TGC,同时生成TGT保存到缓存,CAS服务器会根据TGT生成ST,然后CAS会重定向到给应用系统A,CAS将这个ST和成功登录的用户,以及服务联系在一起。这个ST使用次数(numberOfUses)和有效时间(timeToKill)是可配置的,超过设置的次数或者超过有效时间就会失效。
  • 2、应用系统A收到这个ST之后,它并不知道这个用户已经登录成功,就通过将ST传递给一个校验URL,校验URL拿到Cas系统去验证,CAS通过验证之后返回用户信息,并且将ST作废。
  • 3、应用系统A根据从CAS收到的用户信息将session创建起来,这样我们的应用就拥有了一个自己的session。
  • 4、第一次访问另一个应用系统B,也是没有票据(ST),也没有session,会再次被重定向到CAS系统,CAS系统会去获得TGC,如果该TGC没有失效,则拿到TGT生成ST给用户重定向到系统B,系统B拿到ST之后再去CAS系统验证(同应用系统B的验证方式),验证成功则创建session;如果TGC失效,那么用户还是要重新认证。
  • 5、再去访问系统A时,没有票据,因为票据只能用一次,但是我们有session,所以不用跳转到CAS去签发票据了,直接允许用户访问。
  • 6、用户登出的时候,CAS系统接受请求后,会检测用户的TGC,把对应的session清除,同时会找到所有通过该TGC进行SSO登录的应用服务器URL提交请求,所有的回调请求中,包含一个参数logoutRequest

 

 

 

图片描述
首先,我们来分析下单Web应用系统登录登出的实现机理。Web系统登录登出功能,通常属于系统安全管理模块的一部分。如上篇所说,登录,意味着用户与系统之间的一次会话开始,登出,意味着本次会话的结束。

下图列出整个登录登出会话过程中,用户与系统之间的HTTP交互过程:
图片描述
如图,服务器内部又做了哪些工作呢?

通常服务端在用户登录请求到来时(圈1),会先做认证(Authentication)操作,就是证明这个浏览器请求用户是合法系统用户,一般情况就是验证用户名和密码。

认证通过后,系统紧接着给这个合法用户授权(Authorization),就是根据该用户在此系统中的权限定义,绑定正确的权限信息,为用户后续正确使用系统功能提供安全保障。

最后建立会话,这个可以基于服务器容器提供的Session机制或自己基于Cookie开发的类似功能,建立起本次会话。

登录成功后,当浏览器后续请求来时(圈2),服务器需进行登录状态判断,即判别是否处于会话状态,从而识别操作是否是本次登录用户的操作。

登出时,服务端取消会话,本次登录用户会话结束。下次请求时,系统即判断是非登录用户。
图片描述
上面分析了单Web应用登录登出实现机理。那对于多系统的SSO,该如何实现呢?我们先分析下基本实现思路。

有上面分析可知,单Web应用登录,主要涉及到认证、授权、会话建立、取消会话等几个关键环节。推广到多系统,每个系统也会涉及到认证、授权、会话建立取消等工作。那我们能不能把每个系统的认证工作抽象出来,放到单独的服务应用中取处理,是不是就能解决单点登录问题?

思考方向是正确的,我们把这个统一处理认证服务的应用叫认证中心。当用户访问子系统需要登录时,我们把它引到认证中心,让用户到认证中心去登录认证,认证通过后返回并告知系统用户已登录。当用户再访问另一系统应用时,我们同样引导到认证中心,发现已经登录过,即返回并告知该用户已登录
图片描述
由上图可以看出,原先在各系统中的认证模块,已经剥离出来放到独立的认证中心中去执行。至于授权,每个应用都不一样,可维持原样。会话部分,其实分解成了全局会话和局部会话,这个后面再详细解释。
图片描述
思路是有了,但真正实现这一认证服务器我们还得要具体解决几个关键问题

一、登录信息传递问题

应用系统将登录请求转给认证中心,这个很好解决,我们一个HTTP重定向即可实现。现在的问题是,用户在认证中心登录后,认证中心如何将消息转回给该系统?

这是在单web系统中不存在的问题。我们知道HTTP协议传递消息只能通过请求参数方式或cookie方式,cookie跨域问题不能解决,我们只能通过URL请求参数。

我们可以将认证通过消息做成一个令牌(token)再利用HTTP重定向传递给应用系统。但现在的关键是:该系统如何判断这个令牌的真伪?如果判断这个令牌确实是由认证中心发出的,且是有效的?

我们还需要应用系统和认证中心之间再来个直接通信,来验证这个令牌确实是认证中心发出的,且是有效的。由于应用系统和认证中心是属于服务端之间的通信,不经过用户浏览器,相对是安全的。
图片描述
用户首次登录时流程如下:

1.用户浏览器访问系统A需登录受限资源。

2.系统A发现该请求需要登录,将请求重定向到认证中心,进行登录。

3.认证中心呈现登录页面,用户登录,登录成功后,认证中心重定向请求到系统A,并附上认证通过令牌。

4.系统A与认证中心通信,验证令牌有效,证明用户已登录。

5.系统A将受限资源返给用户。
图片描述
已登录用户首次访问应用群中系统B时:

  1. 浏览器访问另一应用B需登录受限资源。

  2. 系统B发现该请求需要登录,将请求重定向到认证中心,进行登录。

  3. 认证中心发现已经登录,即重定向请求响应到系统B,附带上认证令牌。

  4. 系统B与认证中心通信,验证令牌有效,证明用户已登录。

  5. 系统B将受限资源返回给客户端。

二、登录状态判断问题

用户到认证中心登录后,用户和认证中心之间建立起了会话,我们把这个会话称为全局会话。当用户后续访问系统应用时,我们不可能每次应用请求都到认证中心去判定是否登录,这样效率非常低下,这也是单Web应用不需要考虑的。

我们可以在系统应用和用户浏览器之间建立起局部会话,局部会话保持了客户端与该系统应用的登录状态,局部会话依附于全局会话存在,全局会话消失,局部会话必须消失。

用户访问应用时,首先判断局部会话是否存在,如存在,即认为是登录状态,无需再到认证中心去判断。如不存在,就重定向到认证中心判断全局会话是否存在,如存在,按1提到的方式通知该应用,该应用与客户端就建立起它们之间局部会话,下次请求该应用,就不去认证中心验证了。

三、登出问题

用户在一个系统登出了,访问其它子系统,也应该是登出状态。要想做到这一点,应用除结束本地局部会话外,还应该通知认证中心该用户登出。

认证中心接到登出通知,即可结束全局会话,同时需要通知所有已建立局部会话的子系统,将它们的局部会话销毁。这样,用户访问其它应用时,都显示已登出状态。
图片描述
整个登出流程如下:

1.客户端向应用A发送登出Logout请求。

2.应用A取消本地会话,同时通知认证中心,用户已登出。

3.应用A返回客户端登出请求。

4.认证中心通知所有用户登录访问的应用,用户已登出。



链接:http://www.imooc.com/article/3558



posted @ 2018-11-29 15:24  He_quotes  阅读(295)  评论(0编辑  收藏  举报