在MSDN的文檔“配置跨應用程式的 Forms 身分識別驗證(http://msdn2.microsoft.com/zh-CN/library/eb0zx8fc.aspx)” 中,提出了在Web Farm和多個應用程式之間實現共用身份登陸資訊的方法。這個方法實現的其實是場環境下的身份共用,對於跨子網域名稱的單點登陸,如網易和CSDN的通行證的實現,也有很多朋友給出瞭解決方案,參見:http://www.cnblogs.com/dudu/archive/2005/07/04/186279.html
Form驗證其實是基於身份cookie的驗證。客戶登陸後,產生一個包含使用者身份資訊(包含一個ticket)的cookie,這個cookie的名字就是在web.config裡Authentication節form設定的name資訊,如
<authentication mode="Forms">
<forms loginUrl="login.aspx" name=".ASPXAUTH" path="/" protection="All" ></forms>
</authentication>
這裡,.ASPNETAUTH就是這個Cookie的名字。通過在Request.Cookies集合裡包含這個cookie,實現使用者身份資訊的傳遞。所以,共用身分識別驗證資訊的思路很簡單:只要這個身分識別驗證cookie能在自網域名稱中共用,Form驗證資訊自然可以共用!
共用Cookie的文章網上很多,基本的做法就是設定Cookie的domain屬性。cookie的domain指定了此cookie所關聯的域。domain預設為String.Empty,表示關聯的域是當前Request對應的域。如果domain設定一個子網域名稱,如cookie.Domain="brookes.com",則表示此cookie關聯brookes.com下所有的下級域。因此,可以被www.brookes.com/web2.brookes.com......等共用。
至此,實現跨子網域名稱的Form驗證資訊共用的方法就很簡單:
if (Membership.ValidateUser(userName, password))
...{
FormsAuthentication.SetAuthCookie(userName.Text, false);
HttpCookie cookie = Response.Cookies[FormsAuthentication.FormsCookieName];
cookie.Domain = ".brookes.com";
Response.Cookies.Add(cookie);
FormsAuthentication.RedirectFromLoginPage(userName,false);
}
這個代碼說明的是實現的原理。這裡,實現的自己寫Form驗證的過程。如果使用的是Login控制項,由framework自己完成驗證,怎麼設定這個cookie的domain呢?
可以有三種方式:
1. 在Login.OnLoggedIn事件中處理。這個事件在使用者通過身分識別驗證後觸發,驗證cookie已經存在,可以修改其domain屬性,代碼參考上面;
2. 將驗證使用者、設定AuthCookie的過程寫成一個HttpMoudle。這個方法稍負責,可google代碼
3.有一個最最最簡單的方法,在.net 2.0 中,Authticainon的forms元素新添了一個屬性:domain。這個屬性對應的就是form的AuthCookie的domain屬性。因此,只需要在每個子域的web.config中作如下設定:
<authentication mode="Forms">
<forms loginUrl="login.aspx" name=".ASPXAUTH" path="/" protection="All" domain="brookes.com"></forms>
</authentication>
OK,現在你不需要作任何其他設定了,你的brookes.com下所有的子域都可以共用form驗證身份資訊了!
還要說明幾點:
1. 這個domain屬性會覆蓋在httpCookie配置節的domain屬性設定,但是只會影響到AuthCookie,其他cookie不受影響;
2. 看了上面這一條,當然會想到我可以設定httpCookies配置節,如:
<httpCookies domain="brookes.com"/>
效果是一樣的。不同指出在於,httpCookies指定了網站內所有cookie的domain屬性,這將導致網站內所有的cookie都可以在子域間共用!至於這種共用是需要還是該避免,根據需要具體判斷。
3. 這個domain屬性,我看到在有的文檔裡強調在前面加一個點,如domain=".brookes.com",而MS的文檔裡都沒有這個點。根據我的測試結果,兩個寫法沒有區別,效果一樣。