看圖理解JWT如何用於單點登錄

来源:http://www.cnblogs.com/lyzg/archive/2016/12/06/6132801.html
-Advertisement-
Play Games

單點登錄是我比較喜歡的一個技術解決方案,一方面他能夠提高產品使用的便利性,另一方面他分離了各個應用都需要的登錄服務,對性能以及工作量都有好處。自從上次研究過JWT如何應用於會話管理,加之以前的項目中也一直在使用CAS這個比較流行的單點登錄框架,所以就一直在琢磨如何能夠把JWT跟單點登錄結合起來一起使 ...


單點登錄是我比較喜歡的一個技術解決方案,一方面他能夠提高產品使用的便利性,另一方面他分離了各個應用都需要的登錄服務,對性能以及工作量都有好處。自從上次研究過JWT如何應用於會話管理,加之以前的項目中也一直在使用CAS這個比較流行的單點登錄框架,所以就一直在琢磨如何能夠把JWT跟單點登錄結合起來一起使用,儘量能把兩種技術的優勢都集成到項目中來。本文介紹我從CAS思考得出的SSO的實現方案。

前言

其實CAS這個方案很好,非常強大,它最新的版本已經集成JWT了,所以要是不想自己開發單點登錄的服務的話,完全可以考慮使用CAS。但是我認為,我們在做項目的時候,也許一開始並不需要這麼強大的產品,CAS提供的登錄形式有很多,而我們只需要應用其中的一種;而且它這個框架正是因為強大,所以也會比較複雜,簡單上手容易,但是遇到一些特殊的需求,比如我們想在CAS裡面加入微信登錄,那就需要對它的原理以及API有比較深入的瞭解才行。綜合考慮,還是弄清楚CAS的原理,自己來實現一個基本的SSO服務比較放心。

本文的內容需要對JWT和SSO有一個基本的瞭解,你可以從這兩篇文章來瞭解JWT的用途:3種web會話管理的方式JWT實現token-based會話管理,還可以從下麵的資料來瞭解SSO的內容:SSO_百度百科

方案介紹

本文主要是通過時序圖的方式來介紹JWT SSO的實現原理,具體的技術實現暫時還沒有,不過當你理解了這個方案的原理後,你會覺得最終的實現並不會特別複雜,你可以用任意的平臺語言來實現它。下麵的時序圖,模擬了三個服務,分別是CAS、系統A、系統B,它們分別部署在cas.com,systemA.com和systemB.com;CAS這個服務用來管理SSO的會話;系統A和系統B代表著實際的業務系統。我從五個場景分別來說明這個SSO方案的實現細節。下麵先來看第一個。

場景一:用戶發起對業務系統的第一次訪問,假設他第一次訪問的是系統A的some/page這個頁面,它最終成功訪問到這個頁面的過程是:

sso_1

在這個過程裡面,我認為理解的關鍵點在於:

1. 它用到了兩個cookie(jwt和sid)和三次重定向來完成會話的創建和會話的傳遞;

1. jwt的cookie是寫在systemA.com這個域下的,所以每次重定向到systemA.com的時候,jwt這個cookie只要有就會帶過去;

2. sid的cookie是寫在cas.com這個域下的,所以每次重定向到cas.com的時候,sid這個cookie只要有就會帶過去;

3. 在驗證jwt的時候,如何知道當前用戶已經創建了sso的會話?因為jwt的payload裡面存儲了之前創建的sso 會話的session id,所以當cas拿到jwt,就相當於拿到了session id,然後用這個session id去判斷有沒有的對應的session對象即可。

還要註意的是:CAS服務裡面的session屬於服務端創建的對象,所以要考慮session id唯一性以及session共用(假如CAS採用集群部署的話)的問題。session id的唯一性可以通過用戶名密碼加隨機數然後用hash演算法如md5簡單處理;session共用,可以用memcached或者redis這種專門的支持集群部署的緩存伺服器管理session來處理。

由於服務端session具有生命周期的特點,到期需自動銷毀,所以不要自己去寫session的管理,免得引發其它問題,到github里找開源的緩存管理中間件來處理即可。存儲session對象的時候,只要用session id作為key,session對象本身作為value,存入緩存即可。session對象裡面除了session id,還可以存放登錄之後獲取的用戶信息等業務數據,方便業務系統調用的時候,從session裡面返回會話數據。

場景二:用戶登錄之後,繼續訪問系統A的其它頁面,如some/page2,它的處理過程是:

sso_2

從這一步可以看出,即使登錄之後,也要每次跟CAS校驗jwt的有效性以及會話的有效性,其實jwt的有效性也可以放在業務系統裡面處理的,但是會話的有效性就必須到CAS那邊才能完成了。當CAS拿到jwt裡面的session id之後,就能到session 緩存伺服器裡面去驗證該session id對應的session對象是否存在,不存在,就說明會話已經銷毀了(退出)。

場景三:用戶登錄了系統A之後,再去訪問其他系統如系統B的資源,比如系統B的some/page,它最終能訪問到系統B的some/page的流程是:

sso_3

這個過程的關鍵在於第一次重定向的時候,它會把sid這個cookie帶回給CAS伺服器,所以CAS伺服器能夠判斷出會話是否已經建立,如果已經建立就跳過登錄頁的邏輯。

場景四:用戶繼續訪問系統B的其它資源,如系統B的some/page2:

sso_4

這個場景的邏輯跟場景二完全一致。

場景五:退出登錄,假如它從系統B發起退出,最終的流程是:

sso_5

最重要的是要清除sid的cookie,jwt的cookie可能業務系統都有創建,所以不可能在退出的時候還挨個去清除那些系統的cookie,只要sid一清除,那麼即使那些jwt的cookie在下次訪問的時候還會被傳遞到業務系統的服務端,由於jwt裡面的sid已經無效,所以最後還是會被重定向到CAS登錄頁進行處理。

方案總結

以上方案兩個關鍵的前提:

1. 整個會話管理其實還是基於服務端的session來做的,只不過這個session只存在於CAS服務裡面;

2. CAS之所以信任業務系統的jwt,是因為這個jwt是CAS簽發的,理論上只要認證通過,就可以認為這個jwt是合法的。

jwt本身是不可偽造,不可篡改的,但是不代表非法用戶冒充正常用法發起請求,所以常規的幾個安全策略在實際項目中都應該使用:

1. 使用https

2. 使用http-only的cookie,針對sid和jwt

3. 管理好密鑰

4. 防範CSRF攻擊。

尤其是CSRF攻擊形式,很多都是鑽代碼的漏洞發生的,所以一旦出現CSRF漏洞,並且被人利用,那麼別人就能用獲得的jwt,冒充正常用戶訪問所有業務系統,這個安全問題的後果還是很嚴重的。考慮到這一點,為了在即使有漏洞的情況將損害減至最小,可以在jwt裡面加入一個系統標識,添加一個驗證,只有傳過來的jwt內的系統標識與發起jwt驗證請求的服務一致的情況下,才允許驗證通過。這樣的話,一個非法用戶拿到某個系統的jwt,就不能用來訪問其它業務系統了。

在業務系統跟CAS發起attach/validate請求的時候,也可以在CAS端做些處理,因為這個請求,在一次SSO過程中,一個系統只應該發一次,所以只要之前已經給這個系統簽發過jwt了,那麼後續 同一系統的attach/validate請求都可以忽略掉。

總的來說,這個方案的好處有:

1. 完全分散式,跨平臺,CAS以及業務系統均可採用不同的語言來開發;

2. 業務系統如系統A和系統B,可實現服務端無狀態

3. 假如是自己來實現,那麼可以輕易的在CAS裡面集成用戶註冊服務以及第三方登錄服務,如微信登錄等。

它的缺陷是:

1. 第一次登錄某個系統,需要三次重定向(不過可以優化成兩次);

2. 登錄後的後續請求,每次都需要跟CAS進行會話驗證,所以CAS的性能負載會比較大

3. 登陸後的後續請求,每次都跟CAS交互,也會增加請求響應時間,影響用戶體驗。

本文小結

本文從理論層面介紹了結合jwt來實現SSO的方案原理,希望它能幫助一些朋友更好的理解SSO以及它的實現方法。本文方案參考自CAS的實現流程,你可以從下麵這個資料瞭解CAS的單點登錄實現過程:

https://apereo.github.io/cas/4.1.x/protocol/CAS-Protocol.html

它的流程跟我這個差別不是特別大,但是從清晰層面來說,我寫的還是要更明瞭一些,所以對比起來閱讀,可能理解會更透徹些。

另外,這個方案考慮地不一定很全面,所以要是您發現了其中的問題,還請您幫忙指正,非常感謝:)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 此篇文章同樣是參考SVNKit在wiki的官方文檔做的demo,每個類都可以單獨運行。具體的細節都寫到註釋里了~ 開發背景: SVNKit版本:1.7.14 附上官網下載鏈接:https://www.svnkit.com/org.tmatesoft.svn_1.7.14.standalone.zip ...
  • 1.demo中最常見的方式是在工程下的web.xml中設置(有時候根據業務可能需要設置action,在action中處理邏輯載入跳轉什麼的,比較少): 2.使用Urlrewrite地址重寫,優點還是挺多的,比如安全性能,具體可以百度下,下麵介紹使用方式: 首先還是導入 urlrewrite 的jar ...
  • 調用同步鎖的wait()、notify()、notifyAll()進行線程通信 看這個經典的存取款問題,要求兩個線程存款,兩個線程取款,賬戶里有餘額的時候只能取款,沒餘額的時候只能存款,存取款金額相同。相當於存取款交替進行,金額相同。 線程間通信,需要通過同一個同步監視器(也就是this或者顯式的O ...
  • 前言 日誌是非常重要的,最近有接觸到這個,所以系統的看一下Python這個模塊的用法。本文即為Logging模塊的用法簡介,主要參考文章為Python官方文檔,鏈接見參考列表。 另外,Python的 "HOWTOs文檔" 很詳細,連日誌該怎麼用都寫了,所以有英文閱讀能力的同學建議去閱讀一下。 Log ...
  • 1.安裝依賴包 2、安裝boost庫(對應版本高於或低於這個版本都有問題) 3、添加mysql用戶組 4、下載mysql源碼包並安裝 5.調整配置文件 6. 給安裝目錄設置許可權 7.初始化資料庫 註:初始化後會生成預設密碼,請記錄下來2016-02-17T03:16:36.869627Z 1 [No ...
  • 回到目錄 .Net MVC之所以發展的如些之好,一個很重要原因就是它公開了一組AOP的過濾器,即使用這些過濾器可以方便的攔截controller里的action,並註入我們自己的代碼邏輯,向全局的異常記錄,用戶授權,Url授權,操作行為記錄等,這一大批Lind的基本組件都是實現MVC和API的過濾實 ...
  • 代理模式(Proxy)為其他對象提供一種代理以控制對這個對象的訪問。使用場合,第一,遠程代理,也就是為一個對象在不同的地址空間提供局部代表。這樣可以隱藏一個對象存在於不同地址空間的事實;第二,虛擬代理,是根據需要創建開銷很大的對象。通過它來存在實例化需要很長時間的真實對象;第三,安全代理,用來控制真 ...
  • AccountController .java Java代碼 <!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...