背景
随着系统业务量的不断增长,单个系统的代码量越来越庞大,内部耦合越来越强,后期维护及扩展相当困难;
一般在这种情况下,我们都会采取对系统进行拆分,形成多个子系统,分开部署;
由于系统的拆分,我们又需要解决单点登录的问题。
CAS单点登录介绍
单点登录,指的是在多个应用系统中,用户只需要进行一次登录,就可以认证访问所有组件系统。单点登录有很多种实现方案,本案例总结主要关注Apereo的CAS实现方案,目前主要是基于该方案实现单点登录。
CAS单点登录流程
先来看下整体的流程图,了解下CAS单点登录整体是如何实现的:

- 步骤1、用户访问集成了CAS客户端的子系统EPS;
- 步骤2、CAS客户端的AuthenticationFilter过滤器在请求参数中没找到ST票据也没在Session中找到用户信息,返回302重定向,重定向的url上会带上请求的服务,如:http://localhost:8080/loginPage?service=http%3A%2F%2Flocalhost%3A8080%2Fhome,其中service后面即为请求的服务信息,后续各个步骤都会涉及到该服务,最终返回给用户的信息也是该服务所请求的内容;
- 步骤3、302重定向到CAS服务端登录服务;
- 步骤4、CAS服务端检查Cookie中的TGC,不存在或错误,返回登录页,正是因为这一步才实现了跨系统单点登录功能(如果TGC有效,则会直接签发ST票据,带上ST参数重定向到访问的服务直接到步骤7);
- 步骤5、用户在CAS服务端的登录页上输入登录认证信息,点击提交;
- 步骤6、CAS服务端认证通过后,会创建TGT(可以理解成全局Session),其中TGT的id即TGC会设置在response headers里,如Set-Cookie: CASTGC=TGT-1-01WxsZ5L7M6zGgx5MEXsnOQkyESextITsHlXnh5kXfXVt5yQZ2-HIKCAS,这个步骤很关键,用户的浏览器请求到这个响应后,会在对应的CAS服务端域下,创建该cookie,CAS之所以能实现单点登录,主要是基于该cookie实现的,注意浏览器对cookie的获取是不能跨域的,但是只要跳转到该域的页面,就可以获取到该域的cookie,这也是为什么CAS会有这么多跳转的原因。在该步骤中,创建完TGT后,还需要根据请求的服务签发一个ST票据,并返回302重定向,重定向的url为请求的服务带上ST参数;
- 步骤7、URL中携带ST信息重定向到最初的服务请求,如http://localhost:8081/eps?st=ST-2-zr9dhBFIis4WAzdIePXk-HIKCAS;
- 步骤8、CAS客户端的Cas20ProxyReceivingTicketValidationFilter过滤器拦截到ST参数,发起请求,向CAS服务端验证ST有效性,验证通过获取到用户信息;
- 步骤9、验证通过,CAS服务端返回用户信息;
- 步骤10、在CAS客户端根据ST从CAS服务端获取用户信息成功后,会往自己系统的session中设置用户信息,走完这一步,也就意味着该系统登录完成了,后续对该系统的访问,只需要判断session中是否有用户信息即可。
CAS单点登录时序图
登录流程时序图
时序图
注:以下示例流程图中CAS服务端和基础应用(Base系统)部署在一起,子系统为单独部署的一个子系统。

时序图中各个步骤概述:
用户第一次访问基础应用子系统A中受限的资源:
1、用户访问子基础应用系统A中受保护的资源;
2、基础应用子系统A检测到Session不存在,且请求参数中不包含ST信息,重定向到CAS服务端登录服务;
3、返回302重定向
4、重定向到CAS服务端登录服务
5、CAS服务端没有获取到TGC,或TGC不正确,返回登录页给浏览器;
6、用户输入账户密码提交到CAS服务端认证;
7、CAS服务端认证通过,创建TGT,签发ST,并在响应头中以Set-Cookie 形式,要求浏览器创建TGC Cookie;
8、返回302重定向
9、浏览器携带ST信息访问子系统A;
10、子系统A携带ST去CAS服务端验证;
11、CAS服务端验证ST通过,返回用户信息;
12、返回用户信息
13、子系统A创建Session,并存储用户信息,认证通过,返回受限资源给浏览器;
14、返回请求的页面信息
用户第二次访问基础应用子系统A中受限资源:
15、用户访问子系统A受保护的资源;
16、子系统A检测到Session中的用户信息,返回受限资源给浏览器;
17、返回请求的页面信息
用户第一次访问视频子系统B受限资源:
18、访问门户首页
19、用户访问业务子系统(视频子系统B)受保护的资源;
20、视频子系统B检测到Session不存在用户信息,重定向到CAS服务端登录服务;
21、返回302重定向
22、重定向到CAS服务端登录服务
23、CAS服务端从cookie中获取到TGC,并验证通过,签发ST;
24、返回302重定向到视频子系统B页面
25、浏览器携带ST信息访问视频子系统B;
26、视频子系统B携带ST去CAS服务端验证;
27、CAS服务端验证ST通过,返回用户信息;
28、返回用户信息给视频子系统B
29、子系统B创建Session,并存储用户信息,认证通过,返回受限资源给浏览器;
30、返回请求的视频子系统页面信息
登出流程时序图

时序图中各个步骤概述:
1、用户发起登出请求;
2、CAS服务端从cookie中获取TGC信息,调用destroyTicketGrantingTicket方法开始销毁TGT,
3、遍历由该TGC注册的所有服务,依次发出登出请求(发出的请求带上logoutRequest参数)
该请求会被CAS客户端的SingleSignOutFilter过滤器拦截,拦截后会根据ST从sessionMappingStorage(维护了ST票据和Session的关系)中获取session信息,并销毁;
4、登出请求(基础应用), 同步骤3;
5、CAS客户端销毁基础应用子系统Session
6、CAS客户端销毁子系统Session
7、CAS服务端销毁TGC(清除Cookie),重定向到登出页;
CAS单点登录集成开发过程中的常见问题总结
Session过期、TGT过期问题
首先TGT的过期时间一定要大于Session的过期时间,否则有可能出现TGT已过期,而Session未过期,导致访问其它子系统时,需要重新登录;
由于Session过期机制是会自动延长的,所以无论TGT设置多久,理论上都有可能出现TGT已过期Session未过期的情况;
解决此问题的方案是仿造session过期机制,每隔一段时间,自动调用CAS服务端接口,去重置TGT的最近使用时间,从而延长TGT过期时间;
前后端分离,前端是单页应用,且都是ajax请求问题
目前前后端分离,单页应用的前端开发模式越来越流行,且一般通过ajax请求去获取后端数据,这种前端开发模式去集成Apereo的CAS方案,往往需要做一些调整;
后端不直接返回302重定向,而是和前端做一个约定,如在响应头中加入相应标记,标记该响应需要做跳转处理,以及跳转的URL信息;
有了TGC,为什么还需要ST
假设用户已经登录A系统,然后访问B系统,这时需要建立B系统的session,首先、因为B系统Session不存在用户信息,会重定向到CAS服务端去验证Cookie中的TGC,因为验证TGC是在CAS服务端验证的,而B系统Session的建立,需要B系统后端服务自己去创建Session,设置Session内容,所以这种不通过ST的方式是不能设置B系统的session信息;
而通过签发ST票据,CAS服务端返回一个302重定向,就可以让B系统自己拿着ST去CAS服务端请求用户信息,然后将获取到的用户信息设置到B系统的session中,就OK了。
可能有人会说为什么不直接拿着TGC去验证获取用户信息,然而关键是B系统不能直接获取到TGC,需要重定向到CAS服务端后才能获取该域下Cookie中存储的TGC信息。
2412



被折叠的 条评论
为什么被折叠?



