|
翻譯自CodeProject網(wǎng)站ASP.NET9月份最佳文章:Single Sign On (SSO) for cross-domain ASP.NET applications。
翻譯不妥之處還望大家多多指導、相互交流。
文章分為兩部分:架構設計和程序實現(xiàn),此為第一篇即:架構設計或者叫設計藍圖(Part-I - The design blue print)。:)
簡介
周一的早晨,當你正在納悶周末咋就一眨眼過去了并對接下來漫長的一周感到無比蛋疼之時,你收到了一份Email。
操蛋的是它既不是微軟的offer也不是Google的offer,而是客戶發(fā)來的一個新需求。
他說你們現(xiàn)在幫我們公司做了很多的ASP.NET的網(wǎng)站和忽悠我們上線的各種系統(tǒng),現(xiàn)在我想要我的客戶只要在我們擁有的任何一個網(wǎng)站上登錄一次,那么在我所有的網(wǎng)站上該用戶就都已經(jīng)登錄了,同樣,隨便他從哪個網(wǎng)站上注銷掉,那么他也就從我們所有的網(wǎng)站上注銷了......
你受不了客戶這么羅嗦了,心想不就是要一個SSO功能嗎?使用ASP.NET的form authentication不就可以實現(xiàn)了?因為這樣可以在同域的不用網(wǎng)站下共享cookie,只需要在machineKey設置一樣的配置節(jié)就可以了。放狗一搜,果然有xxxx條結果。放狗找東西可是我們程序員的特長。
開工前,你又掃了一眼郵件,等等,你看到了郵件中的一行話,微微一蛋疼:我們部署了那些網(wǎng)站,但不是都在同一個域名下。
你的客戶狠狠地給你來了個下馬威,好像他早就放狗搜過,因為cookie不能跨域共享,也就不能用來實現(xiàn)跨域驗證了。
這到底是神馬一回事情!(和老外一樣扯玩淡,下面正經(jīng)些)
ASP.NET中的驗證原理
這個問題可能是老生常談了,但在解決難題之前,還是先回歸基礎來看一看事物的本質到底是如何的。因此,我們重溫一下ASP.NET表單驗證的原理也并不壞。
下面是ASP.NET表單驗證的流程圖
驗證流程
2:在此請求中ASP.NET運行時開始查找cookie(由于表單驗證的cookie),如果沒有查找到,那么將跳轉到登錄頁面(登錄頁地址配置在了web.config文件中)
3:在登錄頁面中,你提供了相關的驗證憑證并點擊了登錄按鈕,系統(tǒng)和已存儲的數(shù)據(jù)對比驗證成功后,將Thread.CurrentPrincipal.Identity.Name的屬性值設置成了你提供的用戶名,并在Response中寫入了cookie(同時還寫入了用戶信息和一些如cookie名,失效日期等),并重定向到登錄前的頁面。
4:當你再點擊其他的頁面(或者點擊導航到其他的頁面),瀏覽器發(fā)送驗證的cookie(也可能包含在該網(wǎng)站下寫入的一些其他cookie),這一次已經(jīng)包含了在上一次response中上次驗證獲取到的cookie。
5:和以前一樣,ASP.NET運行時在請求中查找驗證的cookie,這一次找到了,接下來做一些檢查(如失效日期、路徑等等),如果還沒有失效,那么讀取出它的值,恢復出用戶的信息,將Thread.CurrentPrincipal.Identity.Name的屬性值設置成恢復出的用戶名,檢查該用戶是否有權限去訪問當前請求的頁面,如果有,那么頁面執(zhí)行的結果返回到用戶的瀏覽器。
過程很簡單,對嗎?
ASP.NET中多站點同域下的驗證原理
如前所述,ASP.NET表單驗證完全依賴于cookie。那么只要使得不同的站點共享同樣的驗證cookie,那么就可以實現(xiàn)在一個站點登錄實現(xiàn)所有站點的登錄。
HTTP協(xié)議指出,如果兩個站點是同域(或者是子域)的,那么可以共享cookie。本地的處理是瀏覽器根據(jù)網(wǎng)站的URL存儲cookie在本地(磁盤或者內(nèi)存中)。當你請求接下來的任意頁面時,瀏覽器讀取和當前請求的URL匹配的域或子域的cookies,并將此cookies包含在當前的請求中。
現(xiàn)在我們假設有下面兩個網(wǎng)站:
這兩個站點共享同樣的主機地址(同樣的域mydomain.com和子域www),且兩個站點都被配置成了對用戶驗證和授權都使用表單驗證。假設你已經(jīng)登錄過了站點www.mydomain.com/site1,如前所述,你的瀏覽器現(xiàn)在對于站點www.mydomain.com/site1已經(jīng)有了表單驗證的cookie。
現(xiàn)在你隨意訪問以www.mydomain.com/site1開頭的URL,表單驗證的cookie都將被包含在請求被發(fā)送。為什么?是因為此cookie本來就屬于該站點嗎?對的,但不是完全正確。事實上,是因為請求的URL:www.mydomain.com/site1和http://www.mydomain.com/擁有同樣的域名和子域名。
那么在你登錄了www.mydomain.com/site1后,如果你點擊www.mydomain.com/site2下的URL,表單驗證的cookie也將被包含在請求中發(fā)送,這同樣是因為www.mydomain.com/site2與站點http://www.mydomain.com/擁有同樣的域名和子域名,盡管它是不一樣的應用站點(site2)。顯然,在擁有一樣主機地址不一樣的應用站點名之間是可以共享表單驗證cookie的,這樣就實現(xiàn)了一處登錄處處都已經(jīng)登錄的功能(也就是單點登錄)。
然而,ASP.NET沒有允許你僅僅通過將同主機地址下的站點部署上表單驗證后就自動完成了單點登錄。為什么這樣呢?因為每一個不同的ASP.NET web應用程序使用它自己的密鑰去加密和加密cookie(還有諸如ViewState之類的)從而確保了安全。除非你給每一個站點指定了同樣的加密密鑰,那么cookies將被發(fā)送,但是另一個應用站點不能夠讀取驗證cookies的值。
指定同樣的驗證密鑰可以解決這個問題。為每一個ASP.NET應用站點使用同樣的<machinekey>配置節(jié)即可,如下:
<machineKeyvalidationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D"
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"/>
操作流程:
請求http://www.domain1.com/中一個需要驗證的頁面
狀態(tài):瀏覽器沒有驗證cookieNET技術:跨域SSO的實現(xiàn)之一:架構設計,轉載需保留來源!
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。