CAS单点登陆原理解析html
SSO英文全称Single Sign On,单点登陆。SSO是在多个应用系统中,用户只须要登陆一次就能够访问全部相互信任的应用系统。CAS是一种基于http协议的B/S应用系统单点登陆实现方案,认识CAS以前首先要熟悉http协议、Session与Cookie等Web开发基本知识。前端
1.http协议web
HTTP是一个客户端和服务器端请求和应答的标准,咱们全后端开发对接的Rest接口就是基于http协议。http协议包含http请求消息(HttpRequest)和http应答消息(HttpResponse)两部分。参考内容:https://www.cnblogs.com/rayray/p/3729533.html后端
2.Session与Cookie会话机制浏览器
http协议自己是无状态的,但有时候咱们须要http请求保持状态,咱们引入Session与Cookie。
Session用在服务端,用于存储当前全部客户端须要保持的状态值,并为每个客户端生成一个惟一编码,而后经过http响应头Set-Cookie将这个编码发送给客户端。服务器
Cookie用在客户端,用于记录后端发来过的惟一编码,该编码与服务端上的对应的状态值对应,在下一次请求的时候经过http请求头Cookie带上这个编码,服务端就能根据这个编码获取该客户端以前记录的全部状态值。cookie
3.普通登陆session
登陆成功后,在Session中写入登陆用户的信息,退出时清空Session中的用户信息。能够经过filter实现。app
4.CAS单点登陆| 两次前端跳转、一次后端验证编码
4.1首次访问(访问第一个应用系统App1)
CAS首次登陆会通过两次前端跳转、一次后端验证。在应用系统端须要集成CasClient的jar包,把其中的filter配置到站点web.xml中,用于拦截请求、判断登陆、发起跳转或发起验证等。在SSO服务器上部署CasServer的war包,须要配置用户数据源,根据需求修改登陆页面。
第一次前端跳转:客户端访问应用系统,应用系统判断Session发现未登陆,返回302跳转到sso登陆页面,并传递service参数给sso,该service参数有两个做用:
第二次前端跳转:浏览器显示登陆页面,用户输入帐号密码登陆成功后,sso会返回302跳转回到原来请求的应用系统页面,并携带ticket参数,做为认证票据,同时经过Set-Cookie向浏览器记录TGT,(TGT的做用将在下一个应用系统须要登陆的时候体现出做用,是避免重复登陆的关键)
一次后台验证:应用系统接收到带有ticket的请求后,从后台直接向sso服务器发起一个http请求,将service和ticket做为参数,用于验证ticket的有效性;若是ticket有效,sso服务器将返回该ticket对应的登陆用户名。
4.2再次访问(访问第二个应用系统app2)
当用户已经登陆过一个应用系统之后,在同一个浏览器上访问第二个应用系统,根据单点登陆的要求此时不该该再登陆,而是直接进入第二个系统。可是实际上仍是须要通过两次前端跳转、一次后端验证,只不过此时的两次跳转是连续的,中间不会再出现登录页面,用户感觉不到。判断的依据就是前面第4步经过Set-Cookie保存到客户端的TGT(Ticket Granted Cookie )。
相比首次访问,少了以前的第3步(不须要再出现登陆页面),由于此时在第二步跳转时,携带了以前保存的TGT,cas服务端经过TGT能够得知用户信息,所以直接生成ticket返回给应用系统。因此此时是两次连续的302跳转,用户看到的效果就是直接进入第二个应用系统了。
5. 案例讲解
5.1 循环跳转异常案例
异常现象说明:某项目先后端分开部署出现这样一个现象,前端映射域名为http://xxx.abc.cn/gl,后端映射域名为http://xxx.abc.cn/gl/rest,单独访问后端登陆没有任何问题,可是访问前端登录后界面出现反复跳转不停刷新的问题。
异常排查:循环跳转原理,SSO登陆后返回应用系统,应用系统后台认证获取用户信息存入Session,因为某种缘由形成Session信息丢失,致使应用系统认为还未登陆,因而又跳转SSO,此时SSO已经登陆不会再出登录页面,直接生成ticket返回应用系统,应用系统Session再次丢失,进入反复跳转认证的死循环,前端界面表现为不停的刷新。
所以关键问题在于分析Session信息丢失的缘由,通常来说有两种可能:1是系统自己逻辑问题把以前写入Session的登陆信息清空了,2是两个站点的cookie做用域相同而相互覆盖,从而致使后台Session被重置。
分析发现该项目属于第二种状况,先后端cookie都在http://xxx.abc.cn/域下面,解决办法修改cookie做用域或者修改cookie中Jsessionid的命名,防止相互覆盖。