ASP.Net 2.0如何做窗體身份驗證

 

介紹在ASP.Net 2.0如何做窗體身份驗證,並且講解了IIS和ASP.Net2.0窗體身份驗證機制是如何結合在一起的。

綜述

當某一個用戶使用用戶名成功登陸網站時,FormsAuthentication(窗體身份驗證機制,下面統一使用英文術語) 將會創建一個authentication ticket (身份驗證票),通過這個ticket就可以在網站上全程跟蹤這個用戶了。Form authentication ticket通常被包含在一個Cookie裏面,但是Asp.net2.0也支持不使用Cookie的FormsAuthentication,這時候ticket就需要通過Query string 傳遞。

當一個用戶在登陸某個網站時,需要提供身份驗證才能進入網站。如果他還沒有輸入驗證信息(通常是用戶名和密碼),則此用戶將會被重定向到一個登陸頁面。用戶可以在登陸頁面輸入驗證信息,然後這些信息被髮送到服務器與某一個存儲用戶身份信息的介質(例如Sql Server或者某個文件)進行信息對比。在ASP.Net2.0中,可以通過MemberShip Proivder來訪問存儲在諸如Sqlserver的信息。(Provider模式有很多優點,稍後會有文章詳細說明。)當用戶信息通過驗證後,此用戶將獲得允許,訪問他所期望的頁面。

FormsAuthentication通過FormsAuthenticationModule這個類來執行,這個類是ASP.net頁面運行週期的一部分。以下我們將解釋FormsAuthentication在ASP.net2.0中是如何工作的。

IIS 驗證

Asp.net驗證分爲兩步。首先,IIS驗證當前用戶訪問網站所使用的windows帳號是否有權限。如果IIS訪問被配置爲anonymous,則任何用戶都能訪問頁面。

然後,在IIS驗證完畢後,ASP.net開始執行自身的驗證。驗證模式可以在web.config文件中配置,只要在config文件中寫上<authentication mode="Forms" />,那麼ASP.net就知道使用FormsAuthenticationModule 類進行驗證。

Asp.Net Froms Authentication

Froms Authentication 配置:你可以在config文件中配置。配置如下:

<system.web>

<authentication mode="Forms">

<forms loginUrl="Login.aspx"

protection="All"

timeout="30"

name=".ASPXAUTH"

path="/"

requireSSL="false"

slidingExpiration="true"

defaultUrl="default.aspx"

cookieless="UseDeviceProfile" enableCrossAppRedirects="false" />

</authentication>

</system.web>

 這些屬性詳細描述如下:

 loginUrl:指向登陸頁面,你應改把登陸頁面放在一個需要Secure Sockets Layer (SSL)的文件夾裏。這樣才能保障帳號的安全和完整。

 potection:設置爲”ALL”表明authentication ticket是加密的,加密算法被定義在machineKey這個元素中,並且通過哈希算法進行簽名,這個算法也定義在machineKey中。

timout:該屬性定義了驗證session的過期時間。默認值爲30分鐘。

RequireSSL:該屬性被設置爲false,這表明驗證的cookies可以不同過SSL加密傳輸。如果對session的安全性特別重視的話,則需要設置爲true。

slidingExpiration:該屬性被設置爲true,這表示用戶只要在網站上持續保持活動,則session就不會過期。

DefaultUrl:該屬性表示登陸後的默認頁面。

Cookieless:該屬性被設置爲UseDeviceProfile,這表示cookie將在任何支持它的瀏覽器中使用,如果該瀏覽器不支持cookie的話,form authentication將通過url來傳遞authentication ticket

enableCrossAppRedirects:該屬性表示是否可以將通過身份驗證的用戶重定向到其他web應用程序。True表示可以,False表示不可以。


Authorization Configuration(用戶配置)

類UrlAuthorizationModule用來執行保障只有通過身份驗證的用戶才能訪問頁面。你可以在web.config文件中配置這個類:配置如下:
<system.web>

<authorization>

<deny users="?" />

</authorization>

</system.web>

以上配置表明,沒有通過驗證的用戶都將被拒絕訪問頁面。如果一個沒有驗證的用戶試圖訪問頁面,他將會被重定向到loginUrl屬性定義的登陸頁面上。


Forms Authentication 控制流程

Forms Authentication的流程可以參考下圖:

我們來分析一下上面的流程:

第一步:用戶訪問default.aspx頁面,IIS通過了驗證,ASP.Net發現  authorization

元素中包含<deny users="?" />的標籤。

第二步:服務器尋找包含驗證信息的cookie,如果沒有找到這個cookie,用戶將被重定向到登陸頁面。就是loginurl所指定的頁面。用戶將在那個頁面輸入登陸信息。:

第三步:瀏覽器請求瀏覽登錄頁面,同時傳遞ReturnUrl的參數的值。

第四步:服務器調轉到登陸頁面。

第五步:用戶輸入身份驗證信息,並且提交數據,其中還包含ReturnUrl的參數值。

第六部:服務器通過讀取存儲介質(例如sqserver數據庫)驗證用戶的信息。登陸頁面將創建一個包含form authentication ticket的cookie作爲session。

在Asp.net2.0身份驗證可以通過membership系統。Membership類提供了ValidateUser的方法,參考如下:


if (Membership.ValidateUser(userName.Text, password.Text))

{if (Request.QueryString["ReturnUrl"] != null) {FormsAuthentication.RedirectFromLoginPage(userName.Text,false); }

 else { FormsAuthentication.SetAuthCookie(userName.Text, false); } }

else { Response.Write("Invalid UserID and Password");

}

第七步:用戶驗證成功,服務器重新讓瀏覽器指向ReturUrl所指定的頁面。

第八步:在重定向的同時,瀏覽器向default.aspx頁面發送request請求,此次請求包含用戶的forms authentication cookie。

第九步:FormsAuthenticationModule類偵測到forms authentication cookie並且開始驗證,驗證成功後,該類將得到當前的用戶信息,並傳送給HttpContext對象。可以通過HttpContext對象獲得當前用戶的信息。

第10步:驗證成功,來去自如哦!

FormsAuthenticationModule

ASP.Net 2.0在系統默認的web.config文件中定義了一系列的Http模塊(Http Modules).其中包括了一系列的驗證模塊如下:

<httpModules>

...

<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />

<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />

<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" /> ... </httpModules>

在每一次請求時,只能使用一種驗證模塊。通常驗證模式會被定義在web.config文件中:

<authentication mode="Forms" />這句話表示使用FormsAuthentication

FormsAuthenticationModule類會創建一個GenericPrincipal的對象,然後把它存入Http Context中。GenericPrincipal包含一個FormsIdentity的實例的引用,FormsIdentity實例包含了用戶的信息。一般你會通過forms authentication來替你完成以上工作。但是如果你的程序還有別的特殊要求,比如把用戶信息傳遞給一個自定義的類(該類繼承IPrincipal接口),你的程序需要在PostAuthenticate Event事件中編寫代碼。PostAuthenticate Event事件會在      FormsAuthenticationModule驗證forms authentication cookie  並且創建完GenericPrincipal和FormsIdentity對象後觸發,在該事件觸發後,你可以在事件中創建自定義的IPrincipal對象,用此對象封裝FormsIdentity對象,然後把自定義的IPrincipal對象存入HttpContext中。

注意:如果自定義IPricipal對象,你必須在當前線程中設置自定義對象的引用:例如:Thread.CurrentPrincipal=newGenericPrincipal(new GenericIdentity( "Bob", "Passport"), rolesArray);

這樣才能保證HttpContext對象和線程指向同一個驗證用戶的信息。

Forms Authentication Cookies

FormsAuthentication類在調用FormsAuthentication.SetAuthCookie或者FormsAuthentication.RedirectFromLoginPage的方法後會自動創建驗證Cookie;

一個典型的驗證cookie包含以下兩個屬性:

Name:Cookie的名稱

Value:Cookie的值

在一個典型的forms authentication cookie中,cookie的值是加密的,並且創建一個FormAuthenticationTicket的簽名。Cookie包含以下屬性:

Expires:此屬性標識cookie的過期時間,當用戶需要把cookie保存在本地電腦上時,需要設置此屬性。

Domain:這個屬性表明cookie和哪個域相關聯,默認的值爲null

HasKeys:這個屬性表明cookie是否有子鍵。

HttpOnly: 這個屬性表示cookie是否能被客戶端腳本讀取,.net2.0中,這個設置始終爲true;但在客戶端瀏覽器中,只有IE6.0才能識別這個屬性。

Path:這個屬性表明cookie的虛擬目錄。默認的值爲”/”,表示站點根目錄。

Secure:這個屬性表明cookie是否需要加密。如果設置true,cookie將接受SSL加密

Version:這個屬性表明cookie的版本號

創建Forms Authentication Cookies

當某個用戶驗證通過後,Forms Authentication Cookies會被Forms Authentication類在內部自動創建。創建的就是一個FormsAuthenticationTicket類。創建此類的代碼如下:

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,

"userName",

DateTime.Now,

DateTime.Now.AddMinutes(30), // value of time out property false, // Value of IsPersistent property

String.Empty,

FormsAuthentication.FormsCookiePath);

然後如果在web.config文件中,forms元素的protection屬性被設置成ALL

或者Encryption,將對ticket對象進行加密並且創建簽名。加密代碼如下:

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

下面將簡要介紹一下當protection屬性被設置爲true時的流程:

創建一個序列化的forms authentication ticket:即創建此對象爲一個字節數組(byte array)
創建forms authentication ticket的簽名。machineKey中的validation和alidationKey的屬性所設置了生成簽名的算法。我們用此算法計算上面序列化的bytearray,生成MAC(message authentication code)。在默認的選擇中,系統使用的是SHA1的算法。
加密forms authentication ticket,同時我們將創建另外一個序列化的對象,此對象經過加密算法加密。這個加密算法也可在machineKey中的decryption和decryptionKey的屬性中獲得。在asp.net 1.1中使用的是3DES加密,而在asp.net2.0中,使用的是AES加密算法。
創建HttpCookie對象或者生成cookie的query string,(在不支持cookie時,我們只能生成Query String).HttpCookie 對象創建方法代碼如下:
       HttpCookie authCookie = new HttpCookie(

                            FormsAuthentication.FormsCookieName,

                            encryptedTicket);

        加密後的ticket就被添加到了HttpCookie對象中。

設置forms authentication cookie爲安全的。如果forms authentication ticket被配置成爲使用SSL,那麼HttpCookie. Secure的屬性也必須設置成true.在這種情況下,瀏覽器只能通過HTTPS協議傳送Cookies.
設置HttpOnly bit,在asp.net2.0中,這個屬性默認設置完成。
設置當前cookie的屬性。如果需要,可以設置當前cookie的path, domain and和expires屬性
添加cookie至cookiecollection,傳給客戶端。Response.Cookies.Add(authCookie);
每當authentication收到一個請求,FormsAuthenticationModule從客戶端Cookie獲得一個authentication ticket,然後解碼,計算哈希值比對MAC值,這樣就確認了cookie沒有被人爲僞造。最後驗證ticket包含的過期時間。

注 ASP.NET 並不依賴於 Cookie 的到期日期,因爲該時間很容易僞造。

角色授權(Role Authorization)

在 ASP.NET 2.0 中,角色授權已經得到簡化。對用戶進行身份驗證或者將角色細節添加到身份驗證 Cookie 時,不再需要檢索角色信息。.NET Framework 2.0 包括一個角色管理 API,它使您能夠創建和刪除角色,將用戶添加到角色以及從角色刪除用戶。該角色管理 API 將其數據存儲在一個基礎數據存儲中,它通過針對該數據存儲的適當角色提供程序訪問該存儲。以下角色提供程序爲 .NET Framework 2.0 附帶,可以與窗體身份驗證一起使用:


• SQL Server。它是默認的提供程序,將角色信息存儲在 SQL Server 數據庫。
• 授權管理器 (AzMan)。該提供程序使用 XML 文件、Active Directory 或 Active Directory 應用程序模式 (ADAM) 中的一個 AzMan 策略存儲作爲其角色存儲。它通常用於 Intranet 或 Extranet 方案中,其中 Windows 身份驗證和 Active Directory 用於進行身份驗證。

How To: Use Role Manager in ASP.NET 2.0.

Cookieless窗體驗證
ASP.NET 2.0 支持 cookieless 窗體身份驗證。該功能由 forms 元素的 cookieless 屬性控制。該屬性可以設置爲以下四個值之一:

• UseCookies。該值強制 FormsAuthenticationModule 類使用 Cookie 傳輸身份驗證票。
• UseUri。該值指示 FormsAuthenticationModule 類重寫 URL 來傳輸身份驗證票。
• UseDeviceProfile。該值指示 FormsAuthenticationModule 類查看瀏覽器功能。如果瀏覽器支持 Cookie,則使用 Cookie;否則,重寫 URL。

• AutoDetect。該值通過一個動態檢測機制指示 FormsAuthenticationModule 類檢測瀏覽器是否支持 Cookie。如果檢測邏輯表明不支持 Cookie,則重寫 URL。

如果應用程序配置爲使用 cookieless 窗體身份驗證,並且正在使用 FormsAuthentication.RedirectFromLoginPage 方法,則 FormsAuthenticationModule 類自動設置 URL 中的窗體身份驗證票。以下代碼示例顯示了典型 URL 在重寫後的外觀:

http://localhost/CookielessFormsAuthTest/(F(-k9DcsrIY4CAW81Rbju8KRnJ5o_gOQe0I1E_jNJLYm74izyOJK8GWdfoebgePJTEws0Pci7fHgTOUFTJe9jvgA2))/Test.aspx
括號中的 URL 部分包含 Cookie 通常將包含的數據。該數據在請求處理過程中由 ASP.NET 刪除。該步驟由 ASP.NET ISAPI 篩選器執行,而不是在 HttpModule 類中執行。如果從一個 .aspx 頁讀取 Request.Path 屬性,您在 URL 中不會看到任何額外的信息。如果重定向請求,URL 將自動重寫。

注:難以保證 URL 中包含的身份驗證票的安全。當安全性極爲重要時,您應該使用 Cookie 存儲身份驗證票。

MemberShip和LoginControl(成員身份和登錄控件)
ASP.NET 2.0 引入了MemberShip功能和一組登錄 Web 服務器控件,它們簡化了使用窗體身份驗證的應用程序的實現。

MemberShip爲應用程序用戶提供憑據存儲和管理。它還提供一個MemberShip API,可以在使用窗體身份驗證時簡化用戶憑據的驗證任務。該MemberShip功能構建於提供程序模型之上。該模型允許實現和配置指向不同用戶存儲的不同提供程序。ASP.NET 2.0 包括以下成員關係提供程序:

• Active Directory membership provider。該提供程序使用 Active Directory 或 Active Directory 應用程序模式 (ADAM) 用戶存儲。

• SQL Server membership provider。該提供程序使用 SQL Server 用戶存儲。

還可以添加對自定義用戶存儲的支持。例如,可以添加對其他輕量級目錄訪問協議 (LDAP) 目錄或其他現有公共標識存儲的支持。爲此,創建一個從 MembershipProvider 抽象基類繼承的自定義提供程序。

ASP.NET 登錄控件自動使用MemberShip和窗體身份驗證,並封裝提示用戶輸入憑據,驗證用戶,恢復或替換密碼等所需的邏輯。實際上,ASP.NET 登錄控件在窗體身份驗證和MemberShip上提供一個抽象層,並且取代了您使用窗體身份驗證時通常必須進行的大多數或全部工作。

有關使用MemberShip功能和登錄控件的詳細信息,請參閱

How To: Use Membership in ASP.NET 2.0.

Web Farm Scenarios(Web 場方案)
在 Web 場中,無法確保哪個服務器將處理連續請求。如果用戶在一臺服務器上經過身份驗證,但下一個請求在另一臺服務器上進行,則身份驗證票將導致驗證失敗並請求用戶重新進行身份驗證。

machineKey 元素中的 validationKey 和 decryptionKey 屬性用於對窗體身份驗證票進行哈希操作和加密。這些屬性的默認值爲 AutoGenerate.IsolateApps。這些密鑰是針對每個應用程序自動生成的,在每臺服務器上都不同。因此,在一臺計算機上加密的身份驗證票無法在 Web 場中的另一臺計算機或者同一臺 Web 服務器上的另一個應用程序中進行解密和驗證。

爲了解決該問題, Web 場中所有計算機上的 validationKey 和 decryptionKey 值都必須相同。

有關配置 machineKey 元素的詳細信息,請參閱 How To: Configure MachineKey in ASP.NET 2.0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章