单点登录的整理
原文链接:https://blog.csdn.net/sunyuhua_keyboard/article/details/78716831
单WEB应用登录登出实现原理
首先,我们来分析下单Web应用系统登录登出的实现机理。
Web系统登录登出功能,通常属于系统安全管理模块的一部分。登录,意味着用户与系统之间的一次会话开始,登出,意味着本次会话的结束。
1、认证操作:证明这个浏览器请求用户是合法系统用户,一般情况需要验证用户名和密码
2、授权操作:根据用户在此系统中的权限定义,绑定正确的权限信息,为用户后续正确使用系统功能提供安全保障。
3、建立会话操作:基于服务器提供的session机制和浏览器的基于cookie的功能,建立本次会话。
4、状态判断:登录成功后,当浏览器后续请求来时,服务器需要进行登录状态判断,判断是否处于会话状态,从而识别操作是否是本次登录用户的操作。
5、取消会话:登出时,服务器取消会话,本次登录用户会话结束,下次请求时,系统即判断是非登录用户。
多系统登录登出问题
单Web应用登录,主要涉及到认证、授权、会话建立、取消会话等几个关键环节。推广到多系统,每个系统也会涉及到认证、授权、会话建立取消等工作。那我们能不能把每个系统的认证工作抽象出来,放到单独的服务应用中取处理,是不是就能解决单点登录问题?
我们把这个统一处理认证服务的应用叫认证中心。当用户访问子系统需要登录时,我们把它引到认证中心,让用户到认证中心去登录认证,认证通过后返回并告知系统用户已登录。当用户再访问另一系统应用时,我们同样引导到认证中心,发现已经登录过,即返回并告知该用户已登录。
从上图可以看出,原先在各个系统中的认证模块,已经剥离出来放到独立的认证中心中执行。至于授权,每个应用都是不一样的,可以维持原样。会话部分拆分为全局会话和局部会话。
真正实现认证服务器需要解决三个关键问题
1、登录信息传递问题
应用系统将登录请求转给认证中心,这个很好解决,我们一个HTTP 301重定向即可实现。现在的问题是,用户在认证中心登录后,认证中心如何将消息转回给该系统?
这是再单web系统中不存在的问题,我们知道HTTP协议传递消息只能通过请求参数方式或者cookie方式,cookie跨域问题解决不了,我们只能通过URL请求参数。
我们可以将认证通过消息做成一个令牌(token)再利用HTTP 301重定向传递给应用系统。但现在的关键是:该系统如何判断这个令牌的真伪?如何判断这个令牌确实是由认证中心发出的,且是有效的?
我们还需要应用系统和认证中心之间再来一个直接通信,来验证这个令牌确实是认证中心发出的,且是有效的。由于应用系统和认证中心是属于服务器之间的通信,不经过用户浏览器,相对是安全的。
用户首次登录时流程如下:
1、用户浏览器访问系统A需要登录受限的资源
2、系统A发现该请求需要登录,将请求重定向到认证中心,进行登录。
3、认证中心呈现登录页面,用户登录,登录成功后,认证中心冲定向请求到系统A,并附上认证通过令牌。
4、系统A与认证中心通信,验证令牌有效,证明用户已经登录。
5、系统A将受限资源返给用户。
1、浏览器访问另一个应用B需要登录受限的资源
2、系统B发现该请求需要登录,将请求重定向到认证中心,进行登录。
3、认证中心发现已经登录,即重定向请求响应到系统B,附带上认证令牌
4、系统B与认证中心通信,验证令牌有效,证明用户已登录
5、系统B将受限资源返回给客户端
2、登录状态判断问题
用户到认证中心登录后,用户和认证中心之间建立起会话,我们把这个会话成为全局会话,当用户后续访问系统应用时,我们不可能每次应用请求都到认证中心判断是否登录,这样效率非常的地下,单web应用也是不需要 考虑的。
我们可以在系统应用和用户浏览器之间建立起局部会话,局部会话保持了客户端与该系统应用的登录状态,局部会话依附于全局会话存在,全局会话消失,局部会话必须消失
用户访问应用时,首先判断局部会话是否存在,如果存在 ,即认为是登录状态,无需再到认证中心去判断。如不存在,就重定向到认证中心判断全局会话是否存在,如果存在,按照问题1提出的方式通知该应用,该应用与客户端就建立起他们之间的局部会话,下次请求该应用,就不用到认证中心验证了。
3、登出问题
用户在一个系统登出了,访问其他子系统,应该也是登出状态,要想做到这一点,应该除结束本地局部会话外,还应该通知认证中心该用户登出。
认证中心接到登出通知,即可结束全局会话,同时需要通知所有已建立局部会话的子系统,将他们的局部会话销毁,这样,用户访问其他应用时,都显示已登出状态。
整个登出流程:
1、客户端向应用A发送登出请求
2、应用A取消本地会话,同时通知认证中心,用户 已登出
3、应用A返回客户端登出请求
4、认证中心通知所有用户登录访问的应用,用户已登出。
基于CAS开源组件的SSO系统
CAS是一个开源的单点登录系统。
CAS主要分为CAS client 和CAS Server ,其中client 主要是内嵌在需要SSO登录站点的拦截器或者过滤器上
1、首先浏览器向站点1发送请求
2、站点1发现当前请求没有合法的cookie,那么重定向到CAS server上,也就是SSO Server。
3、CAS sever展示登录界面,要求用户登录
4、用户登录后,会写CAS Server的cookie到浏览器,同时生产ticket,利用302跳转到CASClient。这样能保证用户无感知。
5、CAS client利用生成的ticket发送到CAS server进行验证,验证通过后,站点1生成自己的cookie并回写用户浏览器,然后进行登录成功的跳转。
保证当前浏览器在站点1的域名下,有站点1的cookie,同时当前浏览器也有CAS Server的cookie。
站点2,在进行登录时和站点1初次登录流程一致,但是在访问CAS Server的时候,由于当前浏览器已经有了CAS Server的Cookie,那么直接校验通过返回ticket。
ticket通过302跳转跳转到CAS Client上,之后的流程就和站点1是一样的了。如果此时认证失败,那么需要重新走一次登录的过程。
其实感觉很麻烦,但是流程却十分的简单,主要是使用CAS Server的Cookie做校验,同时各自系统维护自己的Cookie。
注意的问题:
CAS Server的Cookie劫持问题,如果CAS Server的Cookie被劫持掉,那么就相当于拿到了一切,所以必须要用HTTPS实现这个过程。
ticket的使用,ticket只能被使用一次,一次校验后立即失效。同时需要有时效性,一般5分钟。最后ticket生成规则要随机,不能被碰撞出来。
对于各自系统自己的Session,也可以依赖于SSO,这样就能保证所有的Session规则一致,便于集中控制。
其实SSO的实现很灵活,CAS只是说了一个原理,至于具体怎么实现,需要平衡安全性、易用性等诸多因素,所以也没有一个固定的实现方案。
SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
例如访问在网易账号中心(http://reg.163.com/ )登录之后
访问以下站点都是登录状态
网易直播 http://v.163.com
网易博客 http://blog.163.com
网易花田 http://love.163.com
网易考拉 https://www.kaola.com
网易Lofter http://www.lofter.com
详细讲解地址:
https://www.zhihu.com/question/22992471/answer/65164090
https://ken.io/note/sso-design-implement