欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
翻譯:Single Sign-On for Everyone - Anders Liu的.NET空間 - 博客園

 

前一陣寫(xiě)了一篇Blog,給出了一些SSO的資料(http://www.cnblogs.com/AndersLiu/archive/2007/05/25/760041.html)?,F在把其中的一篇翻譯出來(lái)。

翻譯:Single Sign-On for Everyone
原文地址:http://bbs.hidotnet.com/22656/ShowPost.aspx

單點(diǎn)登錄(Single Sign-On,SSO)是這些天的熱點(diǎn)話(huà)題。我的很多客戶(hù)都有多個(gè)Web應用,運行在不同子域的不同.NET Framework版本中,甚至是不同的域中。他們都希望用戶(hù)能夠只登錄一次,就能在各個(gè)不同的Web站點(diǎn)中保持登錄狀態(tài)。今天我們來(lái)一起看看如何在各種不同的場(chǎng)景中實(shí)現SSO。我們首先從最簡(jiǎn)單的情況開(kāi)始,然后逐步構建它:

1. 虛擬子目錄中的父、子應用之間的SSO
2. 使用不同授權憑證(用戶(hù)名映射)的SSO
3. 同一域下的兩個(gè)子域中的Web應用之間的SSO
4. 不同.NET版本下的應用之間的SSO
5. 不同域之眾的兩個(gè)應用之間的SSO
6. 混合模式驗證(FormsWindows)中的SSO

1. 虛擬子目錄中的父、子應用之間的SSO

  假設有兩個(gè).NET應用——FooBar,并且Bar位于Foo的一個(gè)虛擬子目錄中(http://foo.com/bar)。兩個(gè)應用都實(shí)現了Forms驗證。實(shí)現Forms驗證需要重寫(xiě)Application_AuthenticateRequest,在這里進(jìn)行驗證,并在驗證成功后調用FormsAuthentication.RedirectFromLoginPage,將登錄的用戶(hù)名(或系統中用于標識用戶(hù)的其他信息)作為參數傳遞進(jìn)去。在ASP.NET中,登錄用戶(hù)狀態(tài)通過(guò)保存在客戶(hù)端Cookie中進(jìn)行持久化。當調用RedirectFromLoginPage時(shí),就會(huì )創(chuàng )建一個(gè)Cookie,其中包含了加密的、帶有登錄用戶(hù)名的FormsAuthenticationTicket。Web.Config中有一節用于定義如何創(chuàng )建該Cookie

<authentication mode="Forms"> 

    
<forms name=".FooAuth" protection="All" timeout="60" loginUrl="login.aspx" /> 

</authentication> 


<authentication mode="Forms"> 

    
<forms name=".BarAuth" protection="All" timeout="60" loginUrl="login.aspx" /> 

</authentication> 

  這里最重要的兩個(gè)屬性是nameprotection。如果在FooBar中,這兩個(gè)屬性是匹配的,那么它們就能在同樣的保護級別上使用相同的Cookie,也就實(shí)現了SSO

<authentication mode="Forms"> 

    
<forms name=".SSOAuth" protection="All" timeout="60" loginUrl="login.aspx" /> 

</authentication>

  當將protection屬性設置為“All”以后,會(huì )同時(shí)對Cookie進(jìn)行加密盒驗證(通過(guò)散列值)。默認的驗證和加密密鑰存儲在Machine.Config中,并且可以在應用程序的Web.Config中重寫(xiě)。其默認值為:

<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey=" AutoGenerate,IsolateApps" validation="SHA1" />

  IsolateApps意味著(zhù)將為每個(gè)應用程序都生成一個(gè)不同的密鑰。我們不能這樣做。為了在所有應用程序中都能加密/解謎Cookie,需要移除IsolateApps屬性,并為使用SSO的所有應用程序指定相同的具體密鑰:

<machineKey validationKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902" decryptionKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC" validation="SHA1" />

  如果你正在針對不同的用戶(hù)存儲進(jìn)行驗證,這就是所有需要做的——對Web.Config的一點(diǎn)修改。

2. 使用不同授權憑證(用戶(hù)名映射)的SSO

  但是,如果Foo應用使用其自己的數據庫,而Bar應用程序使用Membership API或其他形式的驗證呢?在這種情況下,為Foo創(chuàng )建的Cookie并不適用于Bar,因為Bar并不理解其中包含的用戶(hù)名。

  為了使其工作,需要創(chuàng )建第二個(gè)驗證
Cookie,專(zhuān)門(mén)用于Bar應用。還需要一種方式來(lái)將Foo用戶(hù)映射到Bar用戶(hù)。假設Foo應用中登錄了一個(gè)“John Doe”用戶(hù),并且經(jīng)過(guò)檢測發(fā)現這個(gè)用戶(hù)在Bar應用中的標識是“johnd”。在Foo的驗證方法中需要添加下面的代碼:

FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1"johnd", DateTime.Now, DateTime.Now.AddYears(1), true""); 

HttpCookie cookie 
= new HttpCookie(".BarAuth"); 

cookie.Value 
= FormsAuthentication.Encrypt(fat); 

cookie.Expires 
= fat.Expiration; 

HttpContext.Current.Response.Cookies.Add(cookie); 


FormsAuthentication.RedirectFromLoginPage(
"John Doe"); 

  硬編碼的用戶(hù)名僅僅用于演示目的。這段代碼為Bar應用創(chuàng )建了FormsAuthenticationTicket,并用從Bar應用的上下文中找到的用戶(hù)名對其進(jìn)行了填充。然后調用了RedirectFromLoginPageFoo應用創(chuàng )建了正確的驗證Cookie。如果你將兩個(gè)應用程序的驗證Cookie名字改成了相同的(見(jiàn)前面的示例),那么要注意現在他們是不同的了,我們無(wú)需再為每個(gè)站點(diǎn)使用相同的Cookie了:

<authentication mode="Forms"> 

    
<forms name=".FooAuth" protection="All" timeout="60" loginUrl="login.aspx" slidingExpiration="true"/> 

</authentication> 


<authentication mode="Forms"> 

    
<forms name=".BarAuth" protection="All" timeout="60" loginUrl="login.aspx" slidingExpiration="true"/> 

</authentication> 

  現在,只要用戶(hù)登錄到Foo,他就會(huì )被映射到Bar用戶(hù),并在會(huì )隨著(zhù)Foo驗證票據創(chuàng )建一個(gè)Bar驗證票據。如果希望相反的方向也能工作,只需在Bar應用中添加類(lèi)似的代碼即可:

FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1"John Doe", DateTime.Now, DateTime.Now.AddYears(1), true""); 
HttpCookie cookie 
= new HttpCookie(".FooAuth"); 
cookie.Value 
= FormsAuthentication.Encrypt(fat); 
cookie.Expires 
= fat.Expiration; 
HttpContext.Current.Response.Cookies.Add(cookie); 
FormsAuthentication.RedirectFromLoginPage(
"johnd"); 

  但仍然要確保Web.Config中的<machineKey>元素中為兩個(gè)應用提供了匹配的驗證和加密密鑰。

3. 同一域下的兩個(gè)子域中的Web應用之間的SSO

  現在假設FooBar配置為在不同的域http://foo.comhttp://bar.foo.com中運行。前面的代碼都不能使用了,因為Cookies將被存放到不同的文件中,并且應用程序彼此看不到(對方的Cookie)。為了使其能夠工作,我們需要創(chuàng )建域級別的Cookies,并使其對所有子域可見(jiàn)。這樣我們就不能使用RedirectFromLoginPage方法了,因為它不適合創(chuàng )建域級別的Cookie。我們可以手動(dòng)完成這一工作:

FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1"johnd", DateTime.Now, DateTime.Now.AddYears(1), true""); 

HttpCookie cookie 
= new HttpCookie(".BarAuth"); 

cookie.Value 
= FormsAuthentication.Encrypt(fat); 

cookie.Expires 
= fat.Expiration; 

cookie.Domain 
= ".foo.com";  // Highlight 

HttpContext.Current.Response.Cookies.Add(cookie); 


FormsAuthenticationTicket fat 
= new FormsAuthenticationTicket(1"John Doe", DateTime.Now, DateTime.Now.AddYears(1), true""); 

HttpCookie cookie 
= new HttpCookie(".FooAuth"); 

cookie.Value 
= FormsAuthentication.Encrypt(fat); 

cookie.Expires 
= fat.Expiration; 

cookie.Domain 
= ".foo.com";  // Highlight 

HttpContext.Current.Response.Cookies.Add(cookie); 


  注意高亮顯示的行(Anders Liu:為了避免格式問(wèn)題,我使用的是注釋“// Highlight”)。通過(guò)明確地將Cookie的域設定為“.foo.com”,可以確保在http://foo.comhttp://bar.foo.com以及其他子域中都能看到該Cookie。你也可以將Bar的驗證Cookie域設置為“bar.foo.com”。這樣更加安全,因為其他子域看不到它。注意RFC 2109Cookie域值中要求兩個(gè)periods,因此我們在前面添加了一個(gè)period——“.foo.com”。

  另外,確保在每個(gè)應用的
Web.Config中使用相同的<machineKey>元素。只有一種特殊情況,接下來(lái)的小節將探討這一情況。


4.
不同.NET版本下的應用之間的SSO


  有一種可能是
FooBar應用運行在不同版本的.NET中。這是前面的例子就不能工作了。這是因為ASP.NET 2.0使用了不同的加密方法對驗證票據進(jìn)行加密。ASP.NET 1.1使用的是3DES,而ASP.NET 2.0使用的是AES。幸運的是,ASP.NET 2.0為了向后兼容,提供了一個(gè)新的屬性:


<machineKey validationKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902" decryptionKey="F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC" validation="SHA1" decryption="3DES" />

  設置decryption="3DES"可以讓ASP.NET 2.0使用老的加密方法,這樣Cookies就又匹配了。不要向ASP.NET 1.1Web.Config中添加這個(gè)屬性,否則會(huì )導致錯誤。

5. 不同域之眾的兩個(gè)應用之間的SSO

  至此為止我們成功地創(chuàng )建了共享的驗證
Cookie,但如果FooBar位于不同的域——http://foo.comhttp://bar.com——中呢?它們不可能共享Cookie,也不能彼此創(chuàng )建第二Cookie。這種情況下,每個(gè)站點(diǎn)需要創(chuàng )建自己的Cookies,并調用其他站點(diǎn)來(lái)驗證用戶(hù)是否已經(jīng)在別處登錄了。完成這一工作的一種方法就是通過(guò)一些列的重定向。


  為了實(shí)現這一目的,我們分別在兩個(gè)
Web站點(diǎn)中都創(chuàng )建一個(gè)特殊的頁(yè)面(我們稱(chēng)之為sso.aspx)。這個(gè)頁(yè)面的目的就是檢查其域中是否存在Cookie,并返回登錄的用戶(hù)名,這樣其他應用可以在對應的域中創(chuàng )建類(lèi)似的Cookie。下面是來(lái)自Bar.comsso.aspx


<%@ Page Language="C#" %> 


<script language="C#" runat="server"> 



void Page_Load() 



    
// this is our caller, we will need to redirect back to it eventually 

    UriBuilder uri 
= new UriBuilder(Request.UrlReferrer); 


    HttpCookie c 
= HttpContext.Current.Request.Cookies[".BarAuth"]; 


    
if (c != null && c.HasKeys) // the cookie exists! 

    


        
try 

        


            string cookie 
= HttpContext.Current.Server.UrlDecode(c.Value); 

            FormsAuthenticationTicket fat 
= FormsAuthentication.Decrypt(cookie);         


            uri.Query 
= uri.Query + "&ssoauth=" + fat.Name; // add logged-in user name to the query 

        }
 

        
catch 

        


        }
 

    }
 

    Response.Redirect(uri.ToString()); 
// redirect back to the caller 

}
 


</script> 


  這個(gè)頁(yè)面總是會(huì )重定向回調用方。如果Bar.com中存在驗證Cookie,會(huì )解密用戶(hù)名并通過(guò)查詢(xún)字符串中的ssoauth參數返回。

  在另外一端(Foo.com),我們需要像http請求處理流水線(xiàn)中插入一些代碼??梢栽?/span>Application_BeginRequest事件中或者在一個(gè)自定義的HttpHandlerHttpModule中。其用意在于在所有的頁(yè)面請求的盡可能早的地方檢驗驗證Cookie是否存在:

1)
如果Foo.com中存在驗證Cookie,繼續處理請求。此時(shí)用戶(hù)已登錄Foo.com

2) 如果驗證Cookie不存在,重定向到Bar.com/sso.aspx
3) 如果當前請求從Bar.com/sso.aspx重定向回來(lái),分析ssoauth參數并在必要時(shí)創(chuàng )建驗證Cookie。

  這看起來(lái)相當簡(jiǎn)單,但要注意無(wú)限循環(huán):


// see if the user is logged in 

HttpCookie c 
= HttpContext.Current.Request.Cookies[".FooAuth"]; 


if (c != null && c.HasKeys) // the cookie exists! 



    
try 

    


        
string cookie = HttpContext.Current.Server.UrlDecode(c.Value); 

        FormsAuthenticationTicket fat 
= FormsAuthentication.Decrypt(cookie); 

        
return// cookie decrypts successfully, continue processing the page 

    }
 

    
catch 

    


    }
 

}
 


// the authentication cookie doesn‘t exist - ask Bar.com if the user is logged in there 

UriBuilder uri 
= new UriBuilder(Request.UrlReferrer); 


if (uri.Host != "bar.com" || uri.Path != "/sso.aspx"// prevent infinite loop 



    Response.Redirect(http:
//bar.com/sso.aspx); 

}
 

else 



    
// we are here because the request we are processing is actually a response from bar.com 


    
if (Request.QueryString["ssoauth"== null

    


        
// Bar.com also didn‘t have the authentication cookie 

        
return// continue normally, this user is not logged-in 

    }
 else 

    



        
// user is logged in to Bar.com and we got his name! 

        
string userName = (string)Request.QueryString["ssoauth"]; 


        
// let‘s create a cookie with the same name 

        FormsAuthenticationTicket fat 
= new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddYears(1), true""); 

        HttpCookie cookie 
= new HttpCookie(".FooAuth"); 

        cookie.Value 
= FormsAuthentication.Encrypt(fat); 

        cookie.Expires 
= fat.Expiration; 

        HttpContext.Current.Response.Cookies.Add(cookie); 

    }
 

}
 



  兩個(gè)站點(diǎn)都同樣需要這段代碼,但要在每個(gè)站點(diǎn)中使用正確的Cookie名字(.FooAuth vs. .BarAuth)。由于實(shí)際上并沒(méi)有共享Cookie,所以應用程序可以具有不同的<machineKey>元素。無(wú)需同步加密和驗證密鑰。

  很多人可能比較擔心在查詢(xún)字符串中傳遞用戶(hù)名所帶來(lái)的安全隱患。很多方法可以對其進(jìn)行保護。首先,要檢查引用方,不接受來(lái)自任何源的
ssoauth參數,但除了bar.com/sso.asp(或foo.com/sso.aspx)。其次,可以很容易地使用共享密鑰對用戶(hù)名進(jìn)行加密。如果FooBar使用了不同的驗證機制,也可以用類(lèi)似的方式傳遞用戶(hù)的附加信息(例如email地址)。


6.
混合模式驗證(FormsWindows)中的SSO


  到現在為止,我們一直在處理
Forms驗證的情況。但如果我們希望對于Internet用戶(hù)首先采用Forms驗證,如果驗證失敗,再檢查是否是NT域中的Intranet用戶(hù)并進(jìn)行驗證。理論上,我們可以通過(guò)下面的參數來(lái)檢查是否與請求關(guān)聯(lián)了一個(gè)Windows已登錄用戶(hù):

Request.ServerVariables["LOGON_USER"


  然而,除非站點(diǎn)禁用了匿名訪(fǎng)問(wèn),否則該值一直為空。我們可以在
IIS控制面板中禁用匿名訪(fǎng)問(wèn),并啟用集成Windows驗證。這樣LOGON_USER值中將包含已登錄的Intranet用戶(hù)的NT域名。但是所有的Internet用戶(hù)將面臨Windows用戶(hù)名和密碼的挑戰。這不爽。我們希望Internet用戶(hù)可以通過(guò)Forms驗證進(jìn)行登錄,而當失敗的時(shí)候再檢測其Windows域憑證。


  解決這一問(wèn)題的一個(gè)方法是,為
Intranet用戶(hù)提供一個(gè)特殊的入口頁(yè),在這里啟用集成Windows驗證,驗證域用戶(hù),然后創(chuàng )建一個(gè)Forms Cookie并導航到主站點(diǎn)。我們甚至可以通過(guò)Server.Transfer來(lái)隱藏Intranet用戶(hù)訪(fǎng)問(wèn)了不同的頁(yè)面這一事實(shí)。


  還有一種簡(jiǎn)單的解決方案。因為
IIS處理驗證過(guò)程,如果一個(gè)Web站點(diǎn)啟用了匿名訪(fǎng)問(wèn),IIS會(huì )將請求正確地傳遞給ASP.NET 運行時(shí)。它不會(huì )嘗試執行任何類(lèi)型的驗證。然而,如果請求的結果是一個(gè)驗證錯誤(401),IIS會(huì )嘗試特定于該站點(diǎn)的另外一種驗證方法。你可以同時(shí)啟用匿名訪(fǎng)問(wèn)和集成Windows驗證,然后再Forms驗證失敗后執行下面的代碼:


if (System.Web.HttpContext.Current.Request.ServerVariables["LOGON_USER"== ""

    System.Web.HttpContext.Current.Response.StatusCode 
= 401

    System.Web.HttpContext.Current.Response.End(); 

}
 

else 



    
// Request.ServerVariables["LOGON_USER"] has a valid domain user now! 

}
 


  這段代碼執行時(shí),會(huì )首先檢測域用戶(hù)并得到一個(gè)空的字符串。然后它會(huì )終止當前請求并向IIS返回驗證錯誤(401)。這將導致IIS使用另外一種驗證機制,在這種情況下是集成Windows驗證。如果用戶(hù)已經(jīng)登錄到域,請求會(huì )被重復一次,此時(shí)會(huì )填充NT域用戶(hù)信息。如果用戶(hù)沒(méi)有登錄到域,他將有三次機會(huì )輸入Windows用戶(hù)名/密碼。如果用戶(hù)無(wú)法在三次嘗試之內完成登錄,他會(huì )得到403錯誤(拒絕訪(fǎng)問(wèn))。

小結


  我們討論了在兩個(gè)
ASP.NET應用之間進(jìn)行的各種場(chǎng)景的單點(diǎn)登錄。當然也可以實(shí)現不同平臺間的異構系統上的SSO。其思路是同樣的,但實(shí)現起來(lái)可能需要一些創(chuàng )造性的想法。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
webconfig權限控制(轉)
誰(shuí)都能看懂的單點(diǎn)登錄(SSO)實(shí)現方式(附源碼)
SSO 用cookie實(shí)現登錄(同域下)
FormsAuthenticationTicket對象
細說(shuō)ASP.NET Forms身份認證
單點(diǎn)登錄CAS技術(shù)概述
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久