首先讓咱們分析一下一個簡單的登陸是怎麼實現的。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作一些安全性處理,如加密等。