在上一篇文章
如何設計一個單點登入系統(2)?
中主要講解了可跨域SSO系統服務端,客戶端在登入,登出過程中分別應該承擔的職責,本文將重點聊一下具體技術實現,原始碼地址: https://github。com/zhoudapeng/zsso
首先聊服務端的實現,畢竟服務端是整個單點登入系統的大腦
提供登入頁,這個是登入的基礎,所有的接入方在發現當前使用者未登入的情況下都會重定向到sso服務端的登入頁,服務端的邏輯如下:
sso服務端登入頁邏輯
這裡服務端需要做個判斷:
如果當前登入存在。sso。com域下的有效cookie,則證明此使用者之前在其他業務系統登入過,此時無需再讓使用者登入,只需要繫結token與此係統名的關係,然後重定向到此係統的回撥介面(接入方需要在此回撥介面中驗證token,建立本地會話)
不存在。sso。com域下的有效cookie,證明此使用者未登入過,需要跳轉到登入頁,讓使用者登入,為了使用者登入後能直接進入之前的頁面,這裡重定向的過程中需要帶上redirectUrl 這個引數
2。提供登入介面,使用者在登入頁輸入賬號密碼後會透過form表單已post的形式提交到此介面
sso服務端登入form表單提交處理邏輯
如果賬號密碼不對,則再次跳轉到登入頁
賬號密碼匹配,則需要建立token,繫結token與系統名的關係,寫全域性cookie,然後重定向到接入方的回撥地址
3。提供驗證token介面
sso服務端驗證token介面
token不存在,返回驗證失敗
token存在,則取出token的有效截止日期,並繫結token與系統名的關係
4。提供登出介面
sso服務端登出介面
登出時,需要根據token查到所有繫結過的系統名,然後呼叫各個系統的登出介面一一登出。
以上是服務端需要提供的4個介面,下面我們再將一下客戶端的實現
在第一篇文章中講過,一個好的sso系統必須要讓接入方接入簡單,所以本人借鑑了spring auto-driven的思想,也提供了對應的名稱空間,並抽象出了UrlHelper,UserStore,ZssoClient,ZssoConfigResolver4個元件,以及預設實現類,接入方在接入過程中可以隨意拓展這4個元件,然後直接注入到業務層上下文即可。
UrlHelper:拼接url的元件,如無特殊需求不建議重新實現
ZssoClient:跟服務端互動的元件,如無特殊需求不建議重新實現
ZssoConfigResolver:解析配置檔案的元件,預設實現是讀取本地classpath下zsso-client。properties配置檔案,如無特殊需求不建議重新實現
UserStore:存取使用者資訊的元件,包括根據token解析使用者資訊,繫結token與userId關係,解綁token,預設實現只是為了演示用,接入方請務必自己實現此介面,並以userStore的名稱注入到業務層上下文中。
拓展元件使用方式:
拓展UserStore元件配置方式
在spring掃描掉
ZssoBeanDefinitionParser核心程式碼
ComponentInitializer核心程式碼
至此元件初始化的問題已經解決了,另外需要接入方開發的是如下問題:
判斷登入狀態
登入成功回撥介面(包括check token的邏輯)
登出回撥介面
既然每個接入方都有這樣的共性,所以我提供了一個ZssoFilter,在Filter里根據不同的url做不同的處理,接入方只需要配置此Filter即可,Filter內部會自動去獲取元件,接入方只需要拓展相關元件即可,ZssoFilter核心程式碼如下:
ZssoFilter核心邏輯
LoginCallbackFilter已封裝好解析請求引數中token,check token,建立本地會話,跳轉到原頁面等功能
LoginCheckFilter已封裝好判斷當前使用者是否登入及跳轉到登入頁的邏輯
LogoutFilter已封裝好刪除本地會話的功能
程式碼中很多程式碼都是演示類的,尤其是server端的實現,比如保持使用者資訊都是存的本地快取,如果要放到生成環境則需要最佳化下這塊的邏輯,比如放到redis這樣的分散式快取等等。
最後非常感謝大家能在百忙中抽空看我的文章,大家的每一次檢視都是我繼續寫文章的動力,由於本人是典型理科男,文筆可能欠妥,希望大家能夠繼續支援我,我也會繼續努力,繼續堅持原創,但願能讓大家都能有所收穫!