1. 程式人生 > >ASP.Net 2.0窗體身份驗證機制詳解(FormsAuthentication) (轉載)

ASP.Net 2.0窗體身份驗證機制詳解(FormsAuthentication) (轉載)

ASP.Net 2.0窗體身份驗證機制詳解(FormsAuthentication) 收藏 
轉自:http://www.aspxclub.com/l12/c_3689.html 本篇文章介紹了在ASP.Net 2.0如何做窗體身份驗證,並且講解了IIS和ASP.Net2.0窗體身份驗證機制是如何結合在一起的。我們還會詳細講解一下2.0中關於窗體身份驗證的一個類:FormsAuthenticationModule。
  • 綜述
當某一個使用者使用使用者名稱成功登陸網站時,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檔案中配置這個類:配置如下:
<ystem.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 在重寫後的外觀: 注:難以保證 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