首先让咱们分析一下一个简单的登陆是怎么实现的。php
一个简单的登陆流程java
退出登陆
退出登陆主要包括如下两个流程web
一般来讲,服务器端的session会有必定的过时时间,一样的,客户端中包含session id的cookie也有过时时间。若用户登陆后,长时间没有发出访问请求,则等到用户再次访问时,可能服务端的session或客户端的cookie已经失效,致使服务器判断用户为“未登陆”,而实际上用户并无退出登陆过。能够经过实现“自动登陆”来解决这个问题,即在session失效的时候,能够从新自动登陆。数据库
自动登陆的基本思路:跨域
单点登陆(Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,可是又是各自独立的软件系统,提供访问控制的属性。在拥有这项属性的环境中,当用户在某个系统登陆时,就能够获取全部系统的访问权限,不用对每一个单一系统都逐一登陆。这项功能一般是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指,只须要单一的注销动做,就能够结束对于多个系统的访问权限。(即,在多个应用系统中,用户只须要登陆一次就能够访问全部相互信任的应用系统;用户只须要退出登陆一次就能够退出全部的应用系统)服务器
总结:ticket是整个系统的核心,ticket会在用户,应用系统,认证系统的交互中传输,最终达到实现单点登陆的目的。ticket是全部系统对用户的统一的认证标志。yii2
Q1:ticket是什么?由什么组成?
正如前面所说,ticket是全部系统对用户的统一的认证标志。在具体的实现中,咱们能够用cookie来实现ticket的功能。最简单的,一个包含session id的cookie就能够当作是一个ticket。在后续对具体实现的分析中,咱们会更深刻地理解ticket。出于安全须要,一般咱们会对ticket进行加密。要实现SSO的功能,让用户只登陆一次,就必须让应用系统可以识别已经登陆过的用户。应用系统应该能对ticket进行识别和提取,经过与认证系统的通信,能自动判断当前用户是否登陆过,从而完成单点登陆的功能。 cookie
Q2:单点登陆在技术实现上有哪些分类?
在技术实现上,单点登陆能够分为跨子域单点登陆和彻底跨域单点登陆
Q3:什么是跨子域单点登陆?其实现的具体思路是什么?
跨子域单点登陆即在具备相同根域名的站点之间实现单点登陆。例如,有如下站点a.example.com, b.example.com, p.example.com(认证中心),它们都有一个共同的根域名“example.com”。在单点登陆写cookie时,把cookie的域设为它们共同的父域(即“example.com”),这样在不一样的子域名下均可以使用同一个cookie(即ticket);与此同时,可让多个系统共享session信息。
Q4:什么是彻底跨域单点登陆?其实现的具体思路是什么?
彻底跨域单点登陆即具备不一样根域名的站点之间实现单点登陆。实现思路:每一个站点须要有本身的ticket(A-tikcet,B-ticket,P-ticket);当访问应用系统(A,B)时,若没有相应的ticket,则自动重定向到认证系统(P),在认证系统认证得到P-ticket后重定向到应用系统(A或B),用P-tikcet换取相应的A-ticket或B-ticket;注销的时候要注销全部的ticket(P-ticket,A-ticket,B-ticket)
Q5:Q3中共享cookie的方式存在什么局限?
首先,应用群域名得统一;其次,应用群各系统使用的技术(至少是web服务器)要相同,否则cookie的key值(tomcat为JSESSIONID,php为PHPSESSID)不一样,没法维持会话,共享cookie的方式是没法实现跨语言技术平台登陆的,好比java、php、.net系统之间;第三,cookie自己不安全。
跨子域单点登陆的实现相对比较简单,能够基于cookie来实现,基本思想以下:
具体图示以下:
1.当用户访问系统1(域名为a.example.com)时,系统检测到用户的请求中没有ticket(即没有相应的cookie),则判断用户未登陆,将用户重定向到认证中心(带上系统1的url,则认证完后认证中心可将用户重定向会系统1)
2.用户提交登陆表单到认证中心,验证经过后建立相应的session。将session id做为ticket,以cookie的方式发送给用户,并将用户重定向到系统1。(注意,cookie的域为根域“example.com”)
3.用户重定向到系统1(此时会带上相应的cookie做为ticket)。系统1检测到有ticket,则向认证中心发起请求,验证ticket的有效性。
4.认证中心验证ticket的有效性(即确实有对应的session),将校验结果返回给系统1
5.系统1从认证中心获得校验成功的结果后,则能够认为用户“已登陆”。
6.用户继续访问系统2(由于系统2的域名为“b.example.com”,其根域名也为“example.com”,故此时会带上相应的cookie做为ticket)。系统2检测到有ticket,则向认证中心发起请求,验证ticket的有效性。
7.认证中心验证ticket的有效性(即确实有对应的session),将校验结果返回给系统2。
8.系统2从认证中心获得校验成功的结果后,则能够认为用户“已登陆”。
彻底跨域单点登陆的实现思路正如前面所述,这里复述一下:
1.每一个站点须要有本身的ticket(假设:系统1为A-tikcet,系统2为B-ticket,认证中心为P-ticket)
2.当访问应用系统(系统1,系统2)时,若没有相应的ticket,则自动重定向到认证系统(P),在认证系统认证得到P-ticket后重定向到应用系统(系统1或系统2),用P-tikcet换取相应的A-ticket或B-ticket;注销的时候要注销全部的ticket(P-ticket,A-ticket,B-ticket)
具体图示以下:
注意: 在具体的实现中,能够用cookie来实现tikcet。ticket能够是包含session id的cookie。
1.用户访问系统1,系统1发现用户未登陆(没有A-ticket),跳转至认证中心,并带上系统的url做为参数(即回调url,这样认证后就能够跳转回来了)。
2.认证中心发现用户未登陆(没有P-ticket),将用户引导至登陆界面。
3.用户提交登陆信息到认证中心。
4.认证中心校验用户的登陆信息,经过验证后,建立一个全局session,生成一个绑定当前session的P-ticket。而后将P-ticket发送给用户,并将用户重定向到系统1(注意,此时会带上P-ticket)。
5.系统1接收到带有P-ticket的请求后,会向认证中心发出一个请求,验证P-ticket的有效性。
6.认证中心接收到系统1的校验请求,将校验结果返回给系统1。同时若验证经过则会将映射关系(P-ticket,系统1)记录到一个映射表中(称该表为“注册系统表”,即记录那些登陆的子系统与P-ticket的对应关系,这样在用户注销的时候就能够向相应的子系统发送请求,销毁相应的局部session)。
7.系统1接受到认证中心的校验结果,若校验经过,则认为用户是“已登陆”,系统1在自身系统为用户建立一个session(局部session),并生成一个绑定该session的A-ticket,同时将映射关系(A-ticket,P-ticket)记录到本身的一个映射表中(称该表为“ticket映射表”)。而后系统1将A-ticket发送给用户,在后续用户对系统1的访问中,会带上A-ticket,则能够经过A-ticket判断用户是否已经登陆。
8.用户访问系统2,系统2发现用户为登陆(没有B-ticket),跳转到认证中心(此时对认证中心的访问会带上P-ticket),并带上系统2的url做为参数(即回调url,这样认证后就能够跳转回来了)。
9.认证中心发现用户已经登陆(由于用户已经持有P-ticket),确认P-ticket的有效性后便可认为用户“已登陆”。认证中心将用户重定向到系统2(带上P-ticket)。
10.系统2接收到带有P-ticket的请求后,会向认证中心发出一个请求,验证P-ticket的有效性。
11.认证中心接收到系统2的校验请求,将校验结果返回给系统2。同时若验证经过则会将映射关系(P-ticket,系统2)添加到“注册系统表”。
12.系统2接受到认证中心的校验结果,若校验经过,则认为用户是“已登陆”,系统2在自身系统为用户建立一个session(局部session),并生成一个绑定该session的B-ticket,同时将映射关系(A-ticket,P-ticket)记录到本身的一个映射表中(称该表为“ticket映射表”)。而后系统2将B-ticket发送给用户,在后续用户对系统2的访问中,会带上B-ticket,则能够经过B-ticket判断用户是否已经登陆。
注销图示:
1.用户向系统1发起注销请求(会带上A-ticket)。
2.系统1根据映射表“ticket映射表”,取出相应的P-ticket。系统1向认证中心发起注销请求(带上P-ticket)。
3.认证中心接收到注销请求后,验证P-ticket的有效性。若P-ticket有效,则销毁本地的全局session(根据P-ticket)。认证中心从“注册系统表”中查找出与P-ticket相关的全部系统,向全部相关的系统发送注销局部会话请求。
4.系统2接收到认证中心的“注销局部会话”请求,根据P-ticket从“ticket映射表”中取出相应的B-ticket,根据B-ticket销毁本地局部会话。
5.系统1接收到认证中心的“注销局部会话”请求,根据P-ticket从“ticket映射表”中取出相应的A-ticket,根据A-ticket销毁本地局部会话。
值得注意的地方:1.在上面的实现中,咱们能够看到P-ticket是须要在各个端传递的,故出于安全考虑,应该对P-ticket作一些安全性处理,如加密等。