單點登錄的英文名叫做Single Sign On,簡稱SSO。
在以前,一般我們就單系統,所有的功能都在同一個系統上。
后來,我們為了合理利用資源和降低耦合性,于是把單系統拆分成多個子系統。
比如阿里系的淘寶和天貓,很明顯地我們可以知道這時兩個系統,但是你在使用的時候,登陸了天貓,淘寶也會自動登陸。簡單來說,單點登陸就是在多個系統中,用戶只需要登陸一次,各個系統即能感知到該用戶已經登陸。
單系統登陸
眾所周知,HTTP是無狀態的協議,這意味著服務器無法確認用戶的信息。于是乎,W3C就提出了給每一個用戶都發出一個通行證,無論誰訪問的時候都需要攜帶通行證,這樣服務器就可以從通行證上確認用戶的信息。通行證就是Cookie。
如果說Cookie是檢查用戶身上的通行證來確認用戶的身份,那么Session就是通過檢查服務器上的客戶明細表(通行證列表)來確認用戶的身份的。Session相當于在服務器中建立了一份客戶明細表(通行證列表)。
因為HTTP協議是無狀態的,因此Session不能依據HTTP連接來判斷是否是同一個用戶。于是服務器向用戶瀏覽器發送了一個名為JessionId的Cookie,它的值是Session的id值,然后Session就可以根據Cookie來識別是否是同一個用戶。
一般的單系統實現登陸功能都是以下幾個步驟:
1.登陸后,將用戶信息保存在Session對象中。如果在Session對象中能查到,說明已經登陸;如果在Session對象中查不到,說明沒有登陸(或者已經退出登陸)。
2.注銷(退出登陸)時,從Sessoin中刪除用戶的信息。
3.記住我,請求配合Cookie的發送。只要Session還沒有失效,即使在關閉瀏覽器后,重新打開瀏覽器還能保持登陸狀態。這一步驟也就是身份校驗,通常使用攔截器來實現。
多系統登陸的問題與解決方法
Session共享問題
單系統登陸功能主要是用Session保存用戶信息來實現的,但是多個系統就可能有多個Tomcat,而Session是依賴當前系統的Tomcat,所以系統A的Seesion和系統B的Session就存在一個共享的問題。
解決系統之間Session共享問題有以下幾種方案:
1.Tomcat集群Session全局復制(集群內每個Tomcat的Session完全同步),但是這種方案會影響集群的性能,一般不建議。
2.使用反向代理服務器,將請求的IP根據Hash映射到對應的機器上,這樣的話同一個IP地址的請求會一直被轉發到同一臺服務器上。常見的解決方案就是使用Nginx作為反向代理服務器,并使用其ip_hash負載均衡策略。這種方案可能會因為服務器承受不住高并發而宕機導致丟失大部分的Session數據,因此也不建議這么做。
3.把Session放到Redis緩存中,各個服務器讀寫同一個Redis緩存實現Session的共享。Redis的性能好,吞吐量大,還提供持久化到磁盤的功能,一般推薦使用這個方案。
Cookie的跨域問題
當我們請求www.yanggb.com的時候,瀏覽器會自動把www.yanggb.com的Cookie帶過去,但是卻不會把www.renj.com的Cookie帶過去,這時因為域名不同導致的跨域問題。具體地說,這時瀏覽器的同源策略導致的問題,同源策略不允許JS訪問跨域的Cookie,當發送請求的時候需要調用JS去瀏覽器的Cookie庫中獲得Cookie,這時候因為Cookie中保存有域名的屬性作為識別標簽,JS是拿不到非本域的Cookie的。
針對Cookie的跨域問題,主要有幾種解決方案:
1.使用Token代替Session。服務端將Cookie寫到客戶端后,客戶端對Cookie進行解析,將Token解析出來存放到SessionStroage中,此后的請求就把這個Token帶上進行身份校驗。
2.多個域名共享一個Session,在寫入到客戶端的時候設置Cookie的domian。
CAS原理
說到單點登陸的話,肯定要接觸到CAS。CAS的全稱是Central Authentication Service,即中心驗證服務,說白了就是一個獨立的認證中心。
假定現在有3個服務,一個是www.yanggb.com,一個是www.renj.com,還有一個是www.sso.com,其中的www.sso.com就是認證中心。
1.當用戶想要訪問www.yanggb.com受限(需要登陸)的資源的時候,www.yanggb.com發現用戶沒有登陸,就會重定向到www.sso.com認證中心,并將自己的地址作為參數,比如:www.sso.com?service=www.yanggb.com。
2.這時www.sso.com認證服務如果發現用戶沒有登陸,就會將用戶引導至登陸頁面。用戶使用用戶名和密碼進行登陸之后,用戶與認證中心就會建立一個全局的會話(生成Token寫入到Cookie中并保存在瀏覽器上)。然后認證中心就可以重定向會到www.yanggb.com服務,并把Token攜帶過去:www.yanggb.com?token=********。
3.接著www.yanggb.com就會去www.sso.com認證中心校驗這個Token是否正確,如果正確,則www.yanggb.com服務就會和用戶建立局部的會話(創建Session)。
4.接下來,用戶想要訪問www.renj.com受限(需要登陸)的資源,www.renj.com服務發現用戶并沒有登陸,就會重定向到www.sso.com認證中心,同樣將自己的地址作為參數:www.sso.com?service=www.renj.com。因為之前的用戶與www.sso.com認證中心已經建立了全局會話,所以這次www.renj.com重定向到www.sso.com認證中心是可以帶上Cookie的。認證中心根據帶過來的Cookie發現已經與用戶建立了全局會話了,就會重定向到www.renj.com,并把Token攜帶過去給www.renj.com,重定向的地址:www.renj.com?token=********。
5.最后,www.renj.com就會去www.sso.com認證中心校驗這個Token是否正確,如果正確,則www.renj.com就和用戶建立局部會話(創建Session)。
實際上,SSO認證中心就類似于一個中轉站,這就是CAS的核心思想。
?
"世界上最殘忍的不是逃離,而是近在咫尺卻不屬于自己。"