單點登錄、統一認證解決方案

隨着數字化的不斷普及,大型公式或者單位的各個部門逐漸的上了與本身業務相關的各種各樣的系統(在這些系統中,以Web系統居多),幾乎每個系統都需要識別操作者的身份,並根據其不同的身份,分配一定的權限,做一些操作上的限制。結果很多公司或者部門都在各個系統便各自設計了一套用戶資料和權限管理的機制,並提供了用戶登錄證認。這樣滿足了上面的需求,但由此帶來和用戶賬號管理不方便,用戶資料不統一等等問題。在數字化網絡化發展到一定階段時,對用戶資料的整合起來,進行統一的管理變得十分必要。
本文的目的在探討一個簡單有效的方案,將有一定聯繫,擁有統一用戶羣的系統進行關聯,統一用戶的登錄資料,並提供統一的登錄認證入口。統一認證系統與不同應用子系統之間建立一定的信任關係,通過一定的渠道交換認證信息,在保證用戶信息安全的基礎上,實現認證關係的共享機制。使用戶一個地方一次登錄之後,便可以在相應的應用系統羣中遨遊,而不用沒到一個系統就進行登錄,甚至使用不同的賬號和密碼進行登錄。
網站與用戶之間的認證關係,我們一般通過Session來建立,而Session(一般)在不同網站中是不能共享的。本方案的難點在於統一認證系統和應用子系統之間認證信息的共享。用戶在統一認證系統中登錄之後,與統一登錄系統建立了認證關係,如果用戶轉向應用子系統,此時如何與子系統建立認證關係,如何將統一認證系統的認證關係遷移複製到子系統,這將是我們要解決的問題。

ASP.NET的Session保存機制(會話狀態模式)有三種......



ASP.NET 支持三種會話狀態模式: 
InProc:In-Proc 模式將值存儲在 ASP.NET 輔助進程的內存中。因此,該模式提供了對這些值的最快訪問。但是,當 ASP.NET 輔助進程被回收時,狀態數據便會丟失。 
StateServer:與上一模式不同,StateServer 模式使用獨立的 Microsoft Windows 服務來存儲會話變量。因爲該服務獨立於 Microsoft Internet Information Server (IIS),所以它可以在另一獨立的服務器上運行。您可以將此模式用於負載平衡解決方案,因爲多個 Web 服務器可共享會話變量。儘管在重新啓動 IIS 時會話變量不會丟失,但在跨越進程邊界時,性能會受到影響。 
SqlServer:如果會話信息的持久性對於您很重要,那麼您可以使用 SqlServer 模式,以便利用 Microsoft SQL Server 來確保達到最高級別的可靠性。SqlServer 模式類似於進程外模式,只是前者的會話數據維護在 SQL Server 中。SqlServer 模式還讓您能夠利用位於 IIS 進程外的一個狀態存儲區,該狀態存儲區既可位於本地計算機上,也可位於遠程服務器上。

網站的默認Session狀態模式應該是InProc,限制了本系統網站使用。StateServer和SqlServer都作爲擴展,將會話信息存儲在IIS進程之外,實現了不同Web服務器之間的共享。當然,這兩種模式都需要做相應的配置和消耗一定的性能,我們暫且不說這一點。仔細研究發現,這兩種擴展模式主要面向的是網站的分流和負載均衡,共享Session的網站之間的結合是非常非常密切的,並且ASP.NET將所有的實現都進行了封裝,我們無法獲取和記錄每一次共享的細節。這並不適合我們最開始的需求。
假設:A系統通過Session保存了一個User實例,那麼如果B系統需要使用這個Session,則必需擁有A系統中User的細節。如果A、B兩個系統是完全不同,甚至其中不同細節User類,更甚至A、B系統中都不只一處功能使用到Session,Session的命名又總碰巧一致。呵呵,那一切將變得不可思議。當然,如果我A、B爲統一個系統的兩個不同的應用層,那StateServer和SqlServer這兩種方式將能夠很好的滿足需求。至於要滿足我們上面的需求,只能是另外想辦法了。

尋找解決辦法,我們比較關係用戶體驗,那麼先從用戶的使用流程開始.......




根據我們的需求,用戶的體驗一般有兩種:
一、對於使用多個子系統的用戶,將有可能直接登錄統一認證系統,並通過統一系統的子系統連接列表,跳轉到多個子系統;二、對於一些使用單個子系統,或者自爲單具體事情進入我們平臺,或者是登錄超時了,這是他應該向直接進入特定子系統,那麼我們需要將登錄驗證在他進入子系統之前插入。兩種不同方式的三個系統之間的交互過程如下圖所示:


圖 1. 一般步驟,同時登錄多個子系統


圖 2. 直接進入子系統,子系統之間跳轉

我將按照第一種交互方式進行解釋:
1、用戶先與統一登錄系統進行交互,使用唯一的帳號密碼進行登錄,此時不涉及任何子系統;
2、用戶登錄成功後,統一登錄系統將信任的應用子系統列表呈現給用戶;
3、用戶根據需要,選擇子系統連接訪問子系統,用戶與子系統的交互開始;
4、由於用戶與子系統此時還沒有建立認證關係,所以子系統將用戶重定向到統一登錄系統;
5、統一登錄系統驗證用戶的登錄信息,發現用戶已經登錄,便將登錄信息插入到數據庫,再將驗證信息發給用戶,即返回一個等待頁面;
6、用戶將等待頁面中的驗證信息提交(自動)到子系統,子系統獲取認證信息;
7、子系統通過一定的辦法和等待頁面中的驗證信息進行驗證,並與用戶建立了信任關係;
與ASP.NET封裝的實現方案項目,這交互過程看起來十分煩碎,我們還需要自己實現大量的功能。但我們的交互實現過程都是可控的,各個系統之間傳遞的信息內容,什麼時候傳遞,我能都可以限制和約定,並且能夠將每一次系統之間的交互記錄都進行登記,這纔是我們需要的。至於煩碎,其實對用戶來說,增加的步驟就是出現自動提交的等待登錄頁面,如果兩個系統都能正常運行,網絡也沒有出現堵塞,用戶等待的時間將及其短暫,甚至沒能看到頁面。並且我們能夠對等待頁面做一定的美化,使用戶就算看到等待頁面,也不會感到厭煩。

說了這麼多,統一認證系統的應用子系統Session的共享還沒有開始,這是本方案最大的難點......



下面就簡述統一認證系統的應用子系統Session的共享的實現,我和一位同事根據大夥的討論結果,分兩種方式進行實現,詳細情況如下:

第一種方式:通過MD5加密隨機字符串,使用了Web服務實現了子系統和統一認證系統之間的交互驗證。驗證信息包含兩部分用戶在統一登錄系統的Session ID和數據庫中的隨機ID。當子系統將用戶重定向到統一登錄系統的時候,驗證的交互過程開始,詳細步驟如下:
1、統一登錄系統獲取用戶的Session ID和登錄名
2、統一登錄系統將Session ID和登錄名插入到數據庫,產生一個隨機的數據庫ID
3、將Session ID和數據庫ID結合起來,進行MD5加密
4、使用MD5密文和數據庫ID構建一個登錄等待頁面,返回給用戶
5、用戶將登錄等待頁面中的信息自動提交給子系統
6、子系統通過Web服務將MD5密文和數據庫ID提交回統一登錄系統
7、統一登錄系統查詢數據庫,並進行驗證
8、統一登錄系統返回用戶登錄名,並刪除數據庫中的登錄記錄。
9、子系統與用戶建立認證關係


圖 3. MD5隨機加密,Web服務實現驗證


第二種方式:通過對認證信息(登錄令牌)進行非對稱加密,一次交互實現驗證。驗證信息爲一個包含了產生時間的Token類。驗證的交互過程同樣是在重定向到統一登錄系統的時候開始,詳細步驟如下:
1、構建一個包含生成時間的Token類,將Token類序列化
2、使用SHA-1,對序列化Token編碼進行散列,產生驗證碼H
3、將序列化Token編碼和驗證碼H結合,使用公鑰加密
4、使用密文構建一個登錄等待頁面,返回給用戶
5、用戶將登錄等待頁面中的信息自動提交給子系統
6、子系統使用私鑰進行解密
7、子系統分離出散列驗證碼H和序列化Token編碼,並進行SHA-1驗證
8、檢查Token中的生成時間,判斷是否超時
9、子系統與用戶建立認證關係


圖 4. 非對稱加密,一次交互實現驗證

兩種方式各有優缺點,大家很明顯就能看出,我就不做總結。我們最終選擇的方案是第一種,並且在驗證過程中增加了一個Session識別子系統,防止非法的阻塞和冒充。即在應用子系統將用戶重定向到統一認證系統系統時,子系統與用戶建立Session,並在用戶轉交認證信息時,驗證是否原本用戶。防止有非法者獲取了和用戶轉交的認證信息,並在用戶之前提交給子系統,騙取認證。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章