[轉] SSO單點登錄原理和流程分析


WEB的登錄那些事####

說道賬戶登錄和注冊,其實我們每天都在親身感受着,像微博、知乎還有簡書等等。我們總是需要定期的去重新登錄一下,對於這種認證機制,我們都能說出來兩個名詞,Cookie、Session。的確沒錯,Cookie和Session是實現這一切的核心。

為什么會有Cookie和Session?區別是什么?
引入這兩個概念的根本原因是因為Http協議是無狀態的,也就是說它不能建立起多次請求之間的關系。所以需要引入一個能有瀏覽器或服務器保存的一個上下文狀態,也就是Cookie和Session。說到底Session的實現是依賴於Cookie的,因為Cookie是真正的由瀏覽器保存的狀態,Session是利用了JSessionID。在我看來其實兩者有差異,但是根本的依賴是一樣的。Cookie也是有生命周期的,像Session級別或者有一定“壽命”的Cookie。一切是由瀏覽器去維護的。

常見的跨域登錄問題####

之前樓主主要是做賬戶和Passport這方面的工作,其實在跨域這也是碰見了一些問題。

對於同一個根域下的登錄問題#####

如果我們的站點有不止一個業務,那么他們可能部署在不同的機器上,也往往需要不同的域名進行區分。但是所有的業務又都是依賴於一套賬戶體系,那么我們這時候需要通過一次登錄解決所有站點的登錄問題,那么我們這個時候可以使用一個最笨的方法:那就是一次登錄成功,將Cookie寫到根域下,那么這樣所有的站點就能實現,同一個根域下的Cookie共享,自然實現了”單點登錄“。

對於多個根域下的登錄問題#####

如果是多個根域名,那么這種情況下上面的機制就不能實現“單點登錄”了。因為之所以上面可以實現“單點登錄”的效果。是因為瀏覽器和Http協議的支持。但是對於跨根域的站點之間進行Cookie的共享是比較復雜的。

方法1:登錄成功之后將Cookie回寫到多個域名下。

這種辦法可能十分簡單,你可以通過后端的response寫,也可以用前端js去寫,但是必須有對所有需要“單點登錄”的站點進行逐一的寫入。用腳想這種辦法也是行不通的,因為你需要維護一個站點的列表,維護工作十分復雜,同時對於增加站點也會特別痛苦。對於Cookie的銷毀也是十分復雜的,因為還是要對所有域名下的Cookie進行刪除。也就是說將原來需要做的工作增加了n倍。對於小型站點這種辦法是可取的。

方法2:jsonp

搞過前端的可能都知道用jsonp可以做跨域的請求,而我們解決的就是多個域下的統一登錄的問題,好像很順理成章的樣子。但是,登錄是Server端做的吧?我們在Client端做跨域的處理,這怎么看也不是很合理。同時這種辦法需要很大的維護成本,每一次請求都要去固定的域下取相應的Cookie之后再做請求。想想維護有頭疼。

方法3 :引入一個中間態的Server

這種辦法算是一個簡化版的SSO,實現思想也十分的“狡猾”。但是對於小網站做跨域登錄的處理卻十分的有用,具體思路如下:

首先,我們有兩個域名要實現單點登錄,同時我們需要一個中間的Server。

  1. 我們有一個系統域名為xulingbo.net,當我們登錄的時候訪問xulingbo.net/wp-login進行登錄,登錄成功之后將Cookie回寫到xulingbo這個域名下。
  2. 我們還有一個系統域名為javaWeb.com,當我們訪問inside-javaWeb的時候,我們沒有Cookie,那么請求跳轉到中間系統jump。此時需要將當前域名帶到參數中便於jump校驗。這個jump系統是在xulingbo域下的即:jump.xulingbo.net。這時候就能拿到之前寫在xulingbo域下的Cookie。
  3. jump系統在收到了xulingbo域下的Cookie之后,取出xulingbo域下的Cookie,並redirect請求jump.inside-javaWeb.net,這個接口也是在jump系統中,請求后jump系統將Cookie回寫到inside-javaWeb域名下,這樣就實現了簡易的單點登錄。如下圖所示:
 
Paste_Image.png

但是這種方式不是很靈活,對於數據傳輸的安全性沒有保障,並且在銷毀Cookie的時候無能為力,只能全部遍歷的銷毀。

方法4:基於CAS的SSO系統

CAS可不是java中的Compare-And-Swap,它是一個開源的單點登錄系統(SSO)。實現的機制不算復雜但是思想十分靈巧。用CAS也可以快速實現單點登錄。盜圖一張說明sso單個域的登錄和驗證流程:

 
Paste_Image.png

CAS主要分為CAS Client 和CAS Server ,其中Client主要是內嵌在需要SSO登錄站點的攔截器或過濾器上。

  1. 首先瀏覽器向站點1發起請求。
  2. 站點1發現當前請求沒有合法的Cookie,那么重定向到CAS Server上,也就是SSO Server。
  3. CAS Server展示登錄界面,要求用戶登錄。
  4. 用戶登錄后,會寫CAS Server的Cookie到瀏覽器,同時生產ticket,利用一個302跳轉到CASClient。這樣能保證用戶無感知。
  5. CAS Client利用生成的ticket發送到CAS Server進行驗證,驗證通過后,站點1生成自己的Cookie並回寫到用戶瀏覽器,然后進行登錄成功的跳轉。

這樣就能保證當前瀏覽器在站點1的域名下,有站點1的Cookie,同時當前瀏覽器也有CAS Server的Cookie。

接下來看下站點2的登錄:

 
Paste_Image.png

站點2,在進行登錄時和站點1初次登錄流程一致,但是在訪問CAS Server的時候,由於當前瀏覽器已經有了CAS Server的Cookie,那么直接校驗通過返回ticket。
ticket通過302跳轉跳轉到CAS Client上,之后的流程就和站點1是一樣的了。如果此時認證失敗,那么需要重新走一次登錄的過程。

其實感覺很麻煩,但是流程卻十分的簡單,主要是使用CAS Server的Cookie做校驗,同時各自系統維護自己的Cookie。

注意的問題:

  1. CAS Server的Cookie劫持問題,如果CAS Server的Cookie被劫持掉,那么就相當於拿到了一切,所以必須要用HTTPS實現這個過程。
  2. ticket的使用,ticket只能被使用一次,一次校驗后立即失效。同時需要有時效性,一般5分鍾。最后ticket生成規則要隨機,不能被碰撞出來。
  3. 對於各自系統自己的Session,也可以依賴於SSO,這樣就能保證所有的Session規則一致,便於集中控制。

其實SSO的實現很靈活,CAS只是說了一個原理,至於具體怎么實現,需要平衡安全性、易用性等諸多因素,所以也沒有一個固定的實現方案。

上面就是全部我知曉的SSO的實現了,因為之前一直在做相關的東西,這個過程中也做了很多的掙扎和思考,整理出來,幫助所有正在做的童鞋們。如果有什么錯誤還請指出,有什么更好的方法也希望能分享給我。感謝。



作者:一只小哈
鏈接:https://www.jianshu.com/p/c35344d15278
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM