隨著數(shù)字化的不斷普及,大型公式或者單位的各個(gè)部門逐漸的上了與本身業(yè)務(wù)相關(guān)的各種各樣的系統(tǒng)(在這些系統(tǒng)中,以Web系統(tǒng)居多),幾乎每個(gè)系統(tǒng)都 需要識(shí)別操作者的身份,并根據(jù)其不同的身份,分配一定的權(quán)限,做一些操作上的限制。結(jié)果很多公司或者部門都在各個(gè)系統(tǒng)便各自設(shè)計(jì)了一套用戶資料和權(quán)限管理 的機(jī)制,并提供了用戶登錄證認(rèn)。這樣滿足了上面的需求,但由此帶來和用戶賬號(hào)管理不方便,用戶資料不統(tǒng)一等等問題。在數(shù)字化網(wǎng)絡(luò)化發(fā)展到一定階段時(shí),對(duì)用 戶資料的整合起來,進(jìn)行統(tǒng)一的管理變得十分必要。
本文的目的在探討一個(gè)簡(jiǎn)單有效的方案,將有一定聯(lián)系,擁有統(tǒng)一用戶群的系統(tǒng)進(jìn)行關(guān)聯(lián),統(tǒng)一用戶的登錄資料,并提供統(tǒng)一的登錄認(rèn)證入口。統(tǒng)一認(rèn)證系統(tǒng) 與不同應(yīng)用子系統(tǒng)之間建立一定的信任關(guān)系,通過一定的渠道交換認(rèn)證信息,在保證用戶信息安全的基礎(chǔ)上,實(shí)現(xiàn)認(rèn)證關(guān)系的共享機(jī)制。使用戶一個(gè)地方一次登錄之 后,便可以在相應(yīng)的應(yīng)用系統(tǒng)群中遨游,而不用沒到一個(gè)系統(tǒng)就進(jìn)行登錄,甚至使用不同的賬號(hào)和密碼進(jìn)行登錄。
網(wǎng)站與用戶之間的認(rèn)證關(guān)系,我們一般通過Session來建立,而Session(一般)在不同網(wǎng)站中是不能共享的。本方案的難點(diǎn)在于統(tǒng)一認(rèn)證系統(tǒng) 和應(yīng)用子系統(tǒng)之間認(rèn)證信息的共享。用戶在統(tǒng)一認(rèn)證系統(tǒng)中登錄之后,與統(tǒng)一登錄系統(tǒng)建立了認(rèn)證關(guān)系,如果用戶轉(zhuǎn)向應(yīng)用子系統(tǒng),此時(shí)如何與子系統(tǒng)建立認(rèn)證關(guān) 系,如何將統(tǒng)一認(rèn)證系統(tǒng)的認(rèn)證關(guān)系遷移復(fù)制到子系統(tǒng),這將是我們要解決的問題。
ASP.NET的Session保存機(jī)制(會(huì)話狀態(tài)模式)有三種......
ASP.NET 支持三種會(huì)話狀態(tài)模式:
InProc:In-Proc 模式將值存儲(chǔ)在 ASP.NET 輔助進(jìn)程的內(nèi)存中。因此,該模式提供了對(duì)這些值的最快訪問。但是,當(dāng) ASP.NET 輔助進(jìn)程被回收時(shí),狀態(tài)數(shù)據(jù)便會(huì)丟失。
StateServer:與上一模式不同,StateServer 模式使用獨(dú)立的 Microsoft Windows 服務(wù)來存儲(chǔ)會(huì)話變量。因?yàn)樵摲?wù)獨(dú)立于 Microsoft Internet Information Server (IIS),所以它可以在另一獨(dú)立的服務(wù)器上運(yùn)行。您可以將此模式用于負(fù)載平衡解決方案,因?yàn)槎鄠€(gè) Web 服務(wù)器可共享會(huì)話變量。盡管在重新啟動(dòng) IIS 時(shí)會(huì)話變量不會(huì)丟失,但在跨越進(jìn)程邊界時(shí),性能會(huì)受到影響。
SqlServer:如果會(huì)話信息的持久性對(duì)于您很重要,那么您可以使用 SqlServer 模式,以便利用 Microsoft SQL Server 來確保達(dá)到最高級(jí)別的可靠性。SqlServer 模式類似于進(jìn)程外模式,只是前者的會(huì)話數(shù)據(jù)維護(hù)在 SQL Server 中。SqlServer 模式還讓您能夠利用位于 IIS 進(jìn)程外的一個(gè)狀態(tài)存儲(chǔ)區(qū),該狀態(tài)存儲(chǔ)區(qū)既可位于本地計(jì)算機(jī)上,也可位于遠(yuǎn)程服務(wù)器上。
網(wǎng)站的默認(rèn)Session狀態(tài)模式應(yīng)該是InProc,限制了本系統(tǒng)網(wǎng)站使用。StateServer和SqlServer都作為擴(kuò)展,將會(huì)話信息 存儲(chǔ)在IIS進(jìn)程之外,實(shí)現(xiàn)了不同Web服務(wù)器之間的共享。當(dāng)然,這兩種模式都需要做相應(yīng)的配置和消耗一定的性能,我們暫且不說這一點(diǎn)。仔細(xì)研究發(fā)現(xiàn),這 兩種擴(kuò)展模式主要面向的是網(wǎng)站的分流和負(fù)載均衡,共享Session的網(wǎng)站之間的結(jié)合是非常非常密切的,并且ASP.NET將所有的實(shí)現(xiàn)都進(jìn)行了封裝,我 們無法獲取和記錄每一次共享的細(xì)節(jié)。這并不適合我們最開始的需求。
假設(shè):A系統(tǒng)通過Session保存了一個(gè)User實(shí)例,那么如果B系統(tǒng)需要使用這個(gè)Session,則必需擁有A系統(tǒng)中User的細(xì)節(jié)。如果A、 B兩個(gè)系統(tǒng)是完全不同,甚至其中不同細(xì)節(jié)User類,更甚至A、B系統(tǒng)中都不只一處功能使用到Session,Session的命名又總碰巧一致。呵呵, 那一切將變得不可思議。當(dāng)然,如果我A、B為統(tǒng)一個(gè)系統(tǒng)的兩個(gè)不同的應(yīng)用層,那StateServer和SqlServer這兩種方式將能夠很好的滿足需 求。至于要滿足我們上面的需求,只能是另外想辦法了。
尋找解決辦法,我們比較關(guān)系用戶體驗(yàn),那么先從用戶的使用流程開始.......
根據(jù)我們的需求,用戶的體驗(yàn)一般有兩種:
一、對(duì)于使用多個(gè)子系統(tǒng)的用戶,將有可能直接登錄統(tǒng)一認(rèn)證系統(tǒng),并通過統(tǒng)一系統(tǒng)的子系統(tǒng)連接列表,跳轉(zhuǎn)到多個(gè)子系統(tǒng);二、對(duì)于一些使用單個(gè)子系統(tǒng), 或者自為單具體事情進(jìn)入我們平臺(tái),或者是登錄超時(shí)了,這是他應(yīng)該向直接進(jìn)入特定子系統(tǒng),那么我們需要將登錄驗(yàn)證在他進(jìn)入子系統(tǒng)之前插入。兩種不同方式的三 個(gè)系統(tǒng)之間的交互過程如下圖所示:
圖 1. 一般步驟,同時(shí)登錄多個(gè)子系統(tǒng)
圖 2. 直接進(jìn)入子系統(tǒng),子系統(tǒng)之間跳轉(zhuǎn)
我將按照第一種交互方式進(jìn)行解釋:
1、用戶先與統(tǒng)一登錄系統(tǒng)進(jìn)行交互,使用唯一的賬號(hào)密碼進(jìn)行登錄,此時(shí)不涉及任何子系統(tǒng);
2、用戶登錄成功后,統(tǒng)一登錄系統(tǒng)將信任的應(yīng)用子系統(tǒng)列表呈現(xiàn)給用戶;
3、用戶根據(jù)需要,選擇子系統(tǒng)連接訪問子系統(tǒng),用戶與子系統(tǒng)的交互開始;
4、由于用戶與子系統(tǒng)此時(shí)還沒有建立認(rèn)證關(guān)系,所以子系統(tǒng)將用戶重定向到統(tǒng)一登錄系統(tǒng);
5、統(tǒng)一登錄系統(tǒng)驗(yàn)證用戶的登錄信息,發(fā)現(xiàn)用戶已經(jīng)登錄,便將登錄信息插入到數(shù)據(jù)庫,再將驗(yàn)證信息發(fā)給用戶,即返回一個(gè)等待頁面;
6、用戶將等待頁面中的驗(yàn)證信息提交(自動(dòng))到子系統(tǒng),子系統(tǒng)獲取認(rèn)證信息;
7、子系統(tǒng)通過一定的辦法和等待頁面中的驗(yàn)證信息進(jìn)行驗(yàn)證,并與用戶建立了信任關(guān)系;
與ASP.NET封裝的實(shí)現(xiàn)方案項(xiàng)目,這交互過程看起來十分煩碎,我們還需要自己實(shí)現(xiàn)大量的功能。但我們的交互實(shí)現(xiàn)過程都是可控的,各個(gè)系統(tǒng)之間傳 遞的信息內(nèi)容,什么時(shí)候傳遞,我能都可以限制和約定,并且能夠?qū)⒚恳淮蜗到y(tǒng)之間的交互記錄都進(jìn)行登記,這才是我們需要的。至于煩碎,其實(shí)對(duì)用戶來說,增加 的步驟就是出現(xiàn)自動(dòng)提交的等待登錄頁面,如果兩個(gè)系統(tǒng)都能正常運(yùn)行,網(wǎng)絡(luò)也沒有出現(xiàn)堵塞,用戶等待的時(shí)間將及其短暫,甚至沒能看到頁面。并且我們能夠?qū)Φ?待頁面做一定的美化,使用戶就算看到等待頁面,也不會(huì)感到厭煩。
說了這么多,統(tǒng)一認(rèn)證系統(tǒng)的應(yīng)用子系統(tǒng)Session的共享還沒有開始,這是本方案最大的難點(diǎn)......
下面就簡(jiǎn)述統(tǒng)一認(rèn)證系統(tǒng)的應(yīng)用子系統(tǒng)Session的共享的實(shí)現(xiàn),我和一位同事根據(jù)大伙的討論結(jié)果,分兩種方式進(jìn)行實(shí)現(xiàn),詳細(xì)情況如下:
第一種方式:通過MD5加密隨機(jī)字符串,使用了Web服務(wù)實(shí)現(xiàn)了子系統(tǒng)和統(tǒng)一認(rèn)證系統(tǒng)之間的交互驗(yàn)證。驗(yàn)證信息包含兩部分用戶在統(tǒng)一登錄系統(tǒng)的Session ID和數(shù)據(jù)庫中的隨機(jī)ID。當(dāng)子系統(tǒng)將用戶重定向到統(tǒng)一登錄系統(tǒng)的時(shí)候,驗(yàn)證的交互過程開始,詳細(xì)步驟如下:
1、統(tǒng)一登錄系統(tǒng)獲取用戶的Session ID和登錄名
2、統(tǒng)一登錄系統(tǒng)將Session ID和登錄名插入到數(shù)據(jù)庫,產(chǎn)生一個(gè)隨機(jī)的數(shù)據(jù)庫ID
3、將Session ID和數(shù)據(jù)庫ID結(jié)合起來,進(jìn)行MD5加密
4、使用MD5密文和數(shù)據(jù)庫ID構(gòu)建一個(gè)登錄等待頁面,返回給用戶
5、用戶將登錄等待頁面中的信息自動(dòng)提交給子系統(tǒng)
6、子系統(tǒng)通過Web服務(wù)將MD5密文和數(shù)據(jù)庫ID提交回統(tǒng)一登錄系統(tǒng)
7、統(tǒng)一登錄系統(tǒng)查詢數(shù)據(jù)庫,并進(jìn)行驗(yàn)證
8、統(tǒng)一登錄系統(tǒng)返回用戶登錄名,并刪除數(shù)據(jù)庫中的登錄記錄。
9、子系統(tǒng)與用戶建立認(rèn)證關(guān)系
圖 3. MD5隨機(jī)加密,Web服務(wù)實(shí)現(xiàn)驗(yàn)證
第二種方式:通過對(duì)認(rèn)證信息(登錄令牌)進(jìn)行非對(duì)稱加密,一次交互實(shí)現(xiàn)驗(yàn)證。驗(yàn)證信息為一個(gè)包含了產(chǎn)生時(shí)間的Token類。驗(yàn)證的交互過程同樣是在重定向到統(tǒng)一登錄系統(tǒng)的時(shí)候開始,詳細(xì)步驟如下:
1、構(gòu)建一個(gè)包含生成時(shí)間的Token類,將Token類序列化
2、使用SHA-1,對(duì)序列化Token編碼進(jìn)行散列,產(chǎn)生驗(yàn)證碼H
3、將序列化Token編碼和驗(yàn)證碼H結(jié)合,使用公鑰加密
4、使用密文構(gòu)建一個(gè)登錄等待頁面,返回給用戶
5、用戶將登錄等待頁面中的信息自動(dòng)提交給子系統(tǒng)
6、子系統(tǒng)使用私鑰進(jìn)行解密
7、子系統(tǒng)分離出散列驗(yàn)證碼H和序列化Token編碼,并進(jìn)行SHA-1驗(yàn)證
8、檢查Token中的生成時(shí)間,判斷是否超時(shí)
9、子系統(tǒng)與用戶建立認(rèn)證關(guān)系
圖 4. 非對(duì)稱加密,一次交互實(shí)現(xiàn)驗(yàn)證兩種方式各有優(yōu)缺點(diǎn),大家很明顯就能看出,我就不做總結(jié)。我們最終選擇的方案是第一種,并且在驗(yàn)證過程中增加了一個(gè) Session識(shí)別子系統(tǒng),防止非法的阻塞和冒充。即在應(yīng)用子系統(tǒng)將用戶重定向到統(tǒng)一認(rèn)證系統(tǒng)系統(tǒng)時(shí),子系統(tǒng)與用戶建立Session,并在用戶轉(zhuǎn)交認(rèn)證 信息時(shí),驗(yàn)證是否原本用戶。防止有非法者獲取了和用戶轉(zhuǎn)交的認(rèn)證信息,并在用戶之前提交給子系統(tǒng),騙取認(rèn)證。
聯(lián)系客服