1. 程式人生 > >單點登入、統一認證解決方案

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

隨著數字化的不斷普及,大型公式或者單位的各個部門逐漸的上了與本身業務相關的各種各樣的系統(在這些系統中,以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,並在使用者轉交認證資訊時,驗證是否原本使用者。防止有非法者獲取了和使用者轉交的認證資訊,並在使用者之前提交給子系統,騙取認證。