SSO (Single Sign On)
什么是單點登錄:
在大型的互聯網公司中會有多個系統, 多個項目, 雖然這些項目都屬於同一家公司, 但是項目本身其實都是獨立的, 那多個系統可不可以實現共享同一份用戶認證數據呢?
SSO單點登錄就是做這件事, 各個項目之間彼此相互信任, 在其中任意一個系統中進行登錄, 用戶的認證信息會被緩存在用戶本地, 當用戶去訪問其他站點時, 可以復用這份認證信息,而免去了重新登錄的麻煩, 提高用戶體驗感
xxl單點登錄實現的邏輯
其實市面上的SSO框架還是挺多的, xxl是國人寫的, 代碼還是挺容易懂的, 對了解SSO的實現流程也是比較有幫助的
第二點 : 這個項目中會有大量的操作 HttpServletRequest 以及 HttpServletResponse 的代碼, 我們從中肯定能學習到編碼的技巧, 收獲到大量跟 request , reponse, jedis 以及往瀏覽器寫入cookie, 重定向等邏輯, 值得學習一下封裝成工具類使用
xxl的官網是: https://www.xuxueli.com/xxl-sso/
整體的實現思路就是URL+對Cookie或者是token的讀寫實現的跨域, 這是一種怎么樣的實現方式呢? 這就和瀏覽器對cookie的處理有關了, 當我們使用瀏覽訪問某個站點時, 后台的邏輯可能會往瀏覽器中寫入cookie, 這個cookie的作用大家都知道, 就是一種身份標識, 當用戶再次訪問相同的站點時, 瀏覽器會自動的攜帶着這個站點對應的域名下面的cookie
就像下面的圖中一樣, 標識, 這個cookie屬於 xxlssoclient1.com 換句話說,就是用戶訪問其他站點時是不會攜帶這個cookie的

**從上面的分析中我們可以看出, 其實單點登錄的局限性很明顯,不能跨域瀏覽器,因為授權中心的憑證就是存放在用戶的瀏覽器中的cookie **
言歸正傳
用戶請求登錄頁

服務端一啟動首先會先初始化過濾器, 使用這個過濾器將過濾用戶的所有的請求, 校驗用戶是否有權限訪問當前系統, 如果沒有權限的話, 就將用戶的請求轉發到授權中心, 轉發的路徑如下:
http://xxlssoserver.com:8080/xxl-sso-server/login?redirect_url=http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
添加redirect_url參數的意圖很明顯,就是為了從授權中心還會重定向回來
如果授權中心發現,當前訪問的用戶確實沒有任何可用的信息, 就返回一個登錄頁面給用戶
用戶 登錄
用戶在登陸頁面發送登陸的請求到授權中心,會經過如下的流程

經過的流程我在上圖中都標記出來了, 值得注意的是 第二步,會將用戶的授權簽名提前寫回到用戶的瀏覽器中, 因為用戶想訪問的Client中存在攔截器, 專門攔截用戶的請求中是否攜帶合法的簽名,在這里將用戶的請求寫入到瀏覽器中后, 下次用戶在次訪問Client時,就有合法的身份了
第二個注意點就是 ,在授權中心發起了重定向的操作, 重定向的URL如下:
http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/?xxl_sso_sessionid=1000_e92ca0cb494b40eaa8e87a3aceb50279
url中會攜帶着sessionId, 目的是保證了這次請求,能順利的經過Client中檢驗
用戶訪問彼此信任的其他應用是如何做到不用重復授權的, 如下圖

假設Client的URL是:
http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
Client2的URL是
http://xxlssoclient2.com:8081/xxl-sso-web-sample-springboot/
如果Client和Client2共享一個授權中心 , 那么我們在瀏覽器上先使用Client進行一次登錄. 登錄成功后返回登錄頁面
然后我們在這個瀏覽器上繼續訪問Client2的URL, 大家可以看到,Client和Client2的URL中的區別: 就是域名不同, 當然我現在是在本地修改host名字進行模擬 , 實際生產上也是這個樣子, 比如一個大型互聯網公司, 它肯定有不同的項目 , 不同的項目就有自己不同的域名 , 然后我們現在就實現了訪問不同的域名依然能夠完成登錄
結合上圖看, 用戶去訪問Client2時, 因為用戶從來沒有登錄過, 所以被Client2的攔截器攔截下來了, 然后將用戶的請求重定向到授權中心, 但是這次重定向可是很特別的, 因為它會攜帶上第一次訪問Client時,寫入到用戶瀏覽器的Cookie, , 這就好辦了, 授權是認識這個Cookie的, 於是授權中心拿着這個cookie從redis中取出了用戶的信息, 然后將為用戶生成的授權sessionId寫回用戶的瀏覽器中, 這些寫回的授權id, 被瀏覽器存放在 http://xxlssoclient2.com 域名下面, 然后再將這個請求重定向回Client2, 這次從定向回來的請求URL長成下面這樣
http://xxlssoclient2.com:8081/xxl-sso-web-sample-springboot/?xxl_sso_sessionid=1000_6966ea25ae264a28aa3ffe3b89ca7c9a
攜帶了sessionId, 整體一套流程走下來, 客戶端也無需要進行重復登錄... 實現了單點登錄
單點注銷
注銷就是刪除redis緩存中用戶的信息, (xxl的實現中, 授權中心和所有的Client之間共享一個Redis數據庫) 這樣看, 其實刪除也就比較簡單了, 只要我們保證能將redis中的緩存的用戶的信息刪除就ok, 用戶瀏覽器中的 cookie刪除與否其實意義不大, 因為redis中沒有和這個cookie中完全配對的cookie的話, 這個請求仍然會被框架打向登錄頁面
