藉助xxl-sso實現SSO

前言

市場上一下主流的SSO技術搭配方案:css

  1. SpringSecurity + OAuth2
  2. SpringSecurity + CAS 功能較弱,對先後端分離的項目支持不是很好
  3. Shiro + CAS
  4. JWT 能夠自定義需求,靈活擴展鑑權方式

本篇主要是單點登陸,不涉及鑑權,後面文章會再補充java

xxl-sso 是一個國產 SSO 框架,基於 cookies 實現,也許你會考慮跨域問題,雖然 cookies 自己不跨域,但能夠利用它實現跨域的 SSO。git

一、拉取官方示例項目

gitee地址:https://gitee.com/xuxueli0323/xxl-sso
github地址:https://github.com/xuxueli/xxl-ssogithub

模塊說明:
  • xxl-sso-server:中央認證服務,支持集羣
  • xxl-sso-core:Client端依賴
  • xxl-sso-samples:單點登錄Client端接入示例項目
    • xxl-sso-web-sample-springboot:基於Cookie接入方式,供用戶瀏覽器訪問,springboot版本
    • xxl-sso-token-sample-springboot:基於Token接入方式,經常使用於沒法使用Cookie的場景使用,如APP、Cookie被禁用等,springboot版本
依賴環境:

JDK:1.7+
Redis:4.0+web

修改本地host:
127.0.0.1 xxlssoserver.com
127.0.0.1 xxlssoclient1.com
127.0.0.1 xxlssoclient2.com
導入項目後啓動:

修改 application.properties redis爲本地地址後啓動 xxl-sso-server:redis

### xxl-sso
xxl.sso.redis.address=redis://127.0.0.1:6378
xxl.sso.redis.expire.minite=1440

完美報錯,若是你跟我上圖同樣,那麼說明你的 redis 設置了密碼,這個官方示例代碼是沒有配置 redis 密碼的,看控制檯:spring

咱們能夠看到初始化時用到了 redis 的本地地址,那麼只須要知道在哪用了這個地址,那麼確定就會有設置密碼的地方。後端

果不其然,咱們最終發現了,地址是經過 JedisShardInfo 這個對象傳遞進去的,進入這個對象後發現,居然有個 password?這不就是咱們要找的密碼嗎。跨域

再次啓動,成功啓動。瀏覽器

一樣的修改 xxl-sso-samples > xxl-sso-web-samples-sprigboot 的 properties 而後再啓動。

二、認證流程

客戶端端口號被我改爲8085,認證中心保持默認端口號8080

屆時,咱們啓動了兩個項目,瀏覽器訪問第一個域名:http://xxlssoclient1.com:8085/xxl-sso-web-sample-springboot

咱們能夠看到訪問後將被重定向到認證中心 http://xxlssoserver.com:8080/xxl-sso-server ,後面攜帶參數 redirect_url ,其爲界面跳轉前的連接,認證經過後將再次重定向回原來的訪問連接。

上圖爲認證成功後的圖片,會攜帶 xxl_sso_sessionid,其用於識別用戶登錄信息,並會保存至本地兩份 cookie,皆用來保存 xxl_sso_sessionid ,一份當前域名(xxlssoclient1.com),一份認證中心(xxlssoserver.com)。

保存的兩份 xxl_sso_sessionid 值是同樣的。

xxl_sso_sessionid由來

在上圖中的認證界面,點擊登陸後會調用 WebController > doLogin 方法,用戶登陸成功後會生成該用戶的 xxl_sso_sessionid 信息,並保存至 redis 中,同時會把 xxl_sso_sessionid 寫入客戶端 cookie,而後將重定向到 redirect_url,並拼接 xxl_sso_sessionid 參數,以下圖所示。

咱們再來訪問第二個客戶端試試,http://xxlssoclient2.com:8085/xxl-sso-web-sample-springboot,就目前並未向 http://xxlssoclient2.com:8085 寫入任何有關 cookie 用戶會話信息:

神奇的一幕發生了,顯然2號客戶端也成功登錄了,並攜帶了跟客戶端1同樣的 xxl_sso_sessionid 信息,咱們再來看一下 cookie 信息:

xxlssoclient2.com中的xxl_sso_sessionid哪裏來的?

其實經過 debug 發現,在 xxlssoclient1.com 登錄的前提下,再去訪問 xxlssoclient2.com 時,因爲沒有任何登錄信息一樣也是首先會跳轉至認證中心:

還記得客戶端1登錄後在認證中心 xxlssoserver.com 一樣留下 xxl_sso_sessionid 信息嗎?

顯然,客戶端2號再跳轉過來時複用了認證中心的 xxl_sso_sessionid,而後發現存在 xxl_sso_sessionid,且 xxl_sso_sessionid 在 redis 裏也沒過時,則認爲用戶已經登錄了,從新重定向到 xxlssoclient2.com

退出操做

看完了統一登陸,再來看一下退出操做。

退出相對就比較簡單了,主要就是驗證 redis 中的 xxl_sso_sessionid,咱們來看一下退出方法:

首先調用退出方法後會清空當前網站的 cookie、redis 中的 xxl_sso_sessionid,好比在 xxlssoclient1.com、xxlssoclient2.com 都登錄的狀況下,經過 xxlssoclient2.com 退出當前用戶,則首先會清空 xxlssoclient2.com 站點下的 cookie ,同時後臺也會清空當前用戶的 redis,那麼再經過 xxlssoclient1.com 訪問時,儘管攜帶 xxl_sso_sessionid,但此時該信息已通過期,因此會再次重定向認證中心。

xxl-sso小結

如上爲 xxl-sso 架構圖,其核心爲:

sso-server:中央認證服務
sso-client:接入 sso 認證中心的客戶端應用
sso-sessionId:登錄用戶會話ID,SSO 登錄成功後爲用戶自動分配
sso-user:登錄用戶信息,與 SSO sessionId 相對應

登錄流程剖析:
  1. 客戶端訪問受限資源時,將會自動重定向到 SSO Server 進入統一登陸界面
  2. 用戶登陸成功以後將會爲用戶分配 SSO SessionId 並重定向返回來源客戶端端應用,同時附帶分配的 SSO SessionId
  3. 在客戶端的 SSO 過濾器裏驗證 SSO SessionId 無誤,將 SSO SessionId 寫入到用戶瀏覽器客戶端域名下 cookie 中
  4. SSO 過濾器驗證 SSO SessionId 經過,受限資源請求放行
註銷流程剖析:
  1. 用戶在客戶端應用請求註銷時,將會重定向到 SSO Server 自動銷燬全局 SSO SessionId,實現全局銷燬用戶登錄信息;
  2. 而後,訪問接入SSO 保護的任意客戶端應用時,SSO 過濾器均會攔截請求並重定向到 SSO Server 的統一登陸界面;

至此,經過 cookie+redis 解決了多端統一認證,全局 sessionId 解決了 session 共享的問題。

基於Cookie,相關概念
  • 登錄憑證存儲:登錄成功後,用戶登錄憑證被自動存儲在瀏覽器Cookie中
  • 客戶端校驗登錄狀態:經過校驗請求Cookie中的是否包含用戶登陸憑證判斷
  • 系統角色模型:
    -- SSO Server:認證中心,提供用戶登錄、註銷以及登錄狀態校驗等功能
    -- 客戶端應用:受SSO保護的客戶端Web應用,爲用戶瀏覽器訪問提供服務
    -- 用戶:發起請求的用戶,使用瀏覽器訪問

若是 Cookie 被禁用怎麼辦?

xxl-sso 一樣提供了 基於 token 接入方式,用於沒法使用Cookie的場景使用,如APP、Cookie被禁用等,詳細可參考 xxl-sso-token-sample-springboot 項目。

基於Token,相關概念
  • 登錄憑證存儲:登錄成功後,獲取到登陸憑證(xxl_sso_sessionid=xxx),須要主動存儲,如存儲在 localStorage、Sqlite 中
  • 客戶端校驗登錄狀態:經過校驗請求 Header參數 中的是否包含用戶登陸憑證(xxl_sso_sessionid=xxx)判斷;所以,發送請求時須要在 Header 參數 中設置登錄憑證
  • 系統角色模型:
    -- SSO Server:認證中心,提供用戶登錄、註銷以及登錄狀態校驗等功能
    --客戶端應用:受SSO保護的客戶端Web應用,爲用戶請求提供接口服務
    -- 用戶:發起請求的用戶,如使用Android、IOS、桌面客戶端等請求訪問

更多信息請訪問官方文檔:http://www.xuxueli.com/xxl-sso/#/

後面會寫一篇實際項目中接入 xxl-sso 框架的實例。

我建立了一個java相關的公衆號,用來記錄本身的學習之路,感興趣的小夥伴能夠關注一下微信公衆號哈:niceyoo

相關文章
相關標籤/搜索