使用Forms Authentication實現用戶註冊、登錄

一 基礎知識

本文示例代碼:http://www.codeplex.com/a/Release/ProjectReleases.aspx?ReleaseId=9518

前言

  本來使用Forms Authentication進行用戶驗證的方式是最常見的,但系統地闡明其方法的文章並不多見,網上更多的文章都是介紹其中某一部分的使用方法或實現原理,而更多的朋友則發文詢問如何從頭到尾完整第實現用戶的註冊、登錄。因此,本文計劃通過一個實際的例子,介紹如何基於Forms Authentication實現:

  • 用戶註冊(包括密碼的加密存儲)
  • 用戶登錄(包括密碼的驗證、設置安全Cookie)
  • 用戶實體替換(使用自己的類型作爲HttpContext.User的類型)

  有關Forms Authentication的原理等內容不屬於本文的討論範疇,大家可以通過在搜索引擎中輸入“Forms Authentication”、“Forms身份驗證”、“窗體身份驗證”等關鍵詞來查看更多資源。本文僅從實用的角度介紹如何使用這一技術。

不使用Membership

  本文介紹的實現方式不依賴ASP.NET 2.0提供的Membership功能。這主要是因爲,如果使用Membership,就必須用aspnet_regsql.exe實用工具配置數據庫,否則就得自己寫自定義的MembershipProvider。

  如果用aspnet_regsql.exe配置數據庫,就會導致數據庫中出現很多我們實際並不需要的表或字段。此外更重要的是,默認的SqlMembershipProvider給很多數據表添加了ApplicationID列,其初衷可能是希望可以將多個應用程序的用戶全部放在一個庫裏,但又能彼此隔離。但實際情況是,每個應用程序都在其自身的數據庫中保存用戶數據。因此,引入這個ApplicationID無端地在每次查找用戶時增加了額外的條件。

  另一方面,如果考慮自己實現一個MembershipProvider,因爲工作量巨大,有點得不償失。

  但是,如果不使用Membership,也就無法享受ASP.NET 2.0中新增的Login等控件的便利了。

與Forms Authentication相關的配置

  在web.config文件中,<system.web>/<authentication>配置節用於對驗證進行配置。爲<authentication>節點提供mode="Forms"屬性可以啓用Forms Authentication。一個典型的<authentication>配置節如下所示:

<authentication mode="Forms">
     <forms
         name=".ASPXAUTH"
         loginUrl="login.aspx"
         defaultUrl="default.aspx"
         protection="All"
         timeout="30"
         path="/"
         requireSSL="false"
         slidingExpiration="false"
         enableCrossAppRedirects="false"
         cookieless="UseDeviceProfile"
         domain=""
     />
</authentication>

  以上代碼使用的均是默認設置,換言之,如果你的哪項配置屬性與上述代碼一致,則可以省略該屬性。例如<forms name="MyAppAuth" />。下面依次介紹一下各種屬性:

  • name——Cookie的名字。Forms Authentication可能會在驗證後將用戶憑證放在Cookie中,name屬性決定了該Cookie的名字。通過FormsAuthentication.FormsCookieName屬性可以得到該配置值(稍後介紹FromsAuthentication類)。
  • loginUrl——登錄頁的URL。通過FormsAuthentication.LoginUrl屬性可以得到該配置值。當調用FormsAuthentication.RedirectToLoginPage()方法時,客戶端請求將被重定向到該屬性所指定的頁面。loginUrl的默認值爲“login.aspx”,這表明即便不提供該屬性值,ASP.NET也會嘗試到站點根目錄下尋找名爲login.aspx的頁面。
  • defaultUrl——默認頁的URL。通過FormsAuthentication.DefaultUrl屬性得到該配置值。
  • protection——Cookie的保護模式,可取值包括All(同時進行加密和數據驗證)、Encryption(僅加密)、Validation(僅進行數據驗證)和None。爲了安全,該屬性通常從不設置爲None。
  • timeout——Cookie的過期時間。
  • path——Cookie的路徑。可以通過FormsAuthentication.FormsCookiePath屬性得到該配置值。
  • requireSSL——在進行Forms Authentication時,與服務器交互是否要求使用SSL。可以通過FormsAuthentication.RequireSSL屬性得到該配置值。
  • slidingExpiration——是否啓用“彈性過期時間”,如果該屬性設置爲false,從首次驗證之後過timeout時間後Cookie即過期;如果該屬性爲true,則從上次請求該開始過timeout時間才過期,這意味着,在首次驗證後,如果保證每timeout時間內至少發送一個請求,則Cookie將永遠不會過期。通過FormsAuthentication.SlidingExpiration屬性可以得到該配置值。
  • enableCrossAppRedirects——是否可以將以進行了身份驗證的用戶重定向到其他應用程序中。通過FormsAuthentication.EnableCrossAppRedirects屬性可以得到該配置值。爲了安全考慮,通常總是將該屬性設置爲false。
  • cookieless——定義是否使用Cookie以及Cookie的行爲。Forms Authentication可以採用兩種方式在會話中保存用戶憑據信息,一種是使用Cookie,即將用戶憑據記錄到Cookie中,每次發送請求時瀏覽器都會將該Cookie提供給服務器。另一種方式是使用URI,即將用戶憑據當作URL中額外的查詢字符串傳遞給服務器。該屬性有四種取值——UseCookies(無論何時都使用Cookie)、UseUri(從不使用Cookie,僅使用URI)、AutoDetect(檢測設備和瀏覽器,只有當設備支持Cookie並且在瀏覽器中啓用了Cookie時才使用Cookie)和UseDeviceProfile(只檢測設備,只要設備支持Cookie不管瀏覽器是否支持,都是用Cookie)。通過FormsAuthentication.CookieMode屬性可以得到該配置值。通過FormsAuthentication.CookiesSupported屬性可以得到對於當前請求是否使用Cookie傳遞用戶憑證。
  • domain——Cookie的域。通過FormsAuthentication.CookieDomain屬性可以得到該配置值。

  以上針對<system.web>/<authentication>/<forms>節點的介紹非常簡略,基本上是對於文檔進行的額外說明。有關<forms>節點的更多說明,請參見MSDN文檔(http://msdn2.microsoft.com/zh-cn/library/1d3t3c61(VS.85).aspx)。

FormsAuthentication類

  FormsAuthentication類用於輔助我們完成窗體驗證,並進一步完成用戶登錄等功能。該類位於system.web.dll程序集的System.Web.Security命名空間中。通常在Web站點項目中可以直接使用這個類,如果是在類庫項目中使用這個類,請確保引用了system.web.dll。

  前一節已經介紹了FormsAuthentication類的所有屬性。這一節將介紹該類少數幾個常用的方法。

  RedirectToLoginPage方法用於從任何頁面重定向到登錄頁,該方法有兩種重載方式:

public static void RedirectToLoginPage ()
public static void RedirectToLoginPage (string extraQueryString)

  兩種方式均會使瀏覽器重定向到登錄頁(登錄頁的URL由<forms>節點的loginUrl屬性指出)。第二種重載方式還能夠提供額外的查詢字符串。

  RedirectToLoginPage通常在任何非登錄頁的頁面中調用。該方法除了進行重定向之外,還會向URL中附加一個ReturnUrl參數,該參數即爲調用該方法時所在的頁面的URL地址。這是爲了方便登錄後能夠自動回到登錄前所在的頁面。

  RedirectFromLoginPage方法用於從登錄頁跳轉回登錄前頁面。這個“登錄前”頁面即由訪問登錄頁時提供的ReturnUrl參數指定。如果沒有提供ReturnUrl參數(例如,不是使用RedirectToLoginPage方法而是用其他手段重定向到或直接訪問登錄頁時),則該方法會自動跳轉到由<forms>節點的defaultUrl屬性所指定的默認頁。

  此外,如果<forms>節點的enableCrossAppRedirects屬性被設置爲false,ReturnUrl參數所指定的路徑必須是當前Web應用程序中的路徑,否則(如提供其他站點下的路徑)也將返回到默認頁。

  RedirectFromLoginPage方法有兩種重載形式:

public static void RedirectFromLoginPage
    (string userName, bool createPersistentCookie)

public static void RedirectFromLoginPage 
    (string userName, bool createPersistentCookie, string strCookiePath)

  userName參數表示用戶的標識(如用戶名、用戶ID等);createPersistentCookie參數表示是否“記住我”;strCookiePath參數表示Cookie路徑。

  RedirectFromLoginPage方法除了完成重定向之外,還會將經過加密(是否加密取決於<forms>節點的protection屬性)的用戶憑據存放到Cookie或Uri中。在後續訪問中,只要Cookie沒有過期,則將可以通過HttpContext.User.Identity.Name屬性得到這裏傳入的userName屬性。

  此外,FormsAuthentication還有一個SignOut方法,用於完成用戶註銷。其原理是從Cookie或Uri中移除用戶憑據。

小結

  好了,至此所需要掌握的基礎知識就齊備了,接下來我們將實現用戶註冊、登錄等功能。

二 用戶註冊與登錄

  從這一部分開始,我們將通過一個實際的完整示例來看一下如何實現用戶註冊與登錄。在介紹註冊與登錄之前,我們首先介紹一下如何判斷用戶是否已登錄,並未後面的示例編寫一些基礎代碼。

判斷用戶是否已經登錄

  首先,在Web站點項目中添加一個MasterPage,例如MasterPage.master。在這個母版頁的ContentPlaceHolder控件之前、<From>標籤之內插入如下代碼:

<asp:Panel ID="pnlAnonymous" runat="server">
     <asp:LinkButton ID="btnLogin" runat="server" Text="登錄" OnClick="btnLogin_Click">
     </asp:LinkButton> |
     <asp:HyperLink ID="lnkRegister" runat="server" NavigateUrl="~/register.aspx" Text="註冊">
     </asp:HyperLink>
</asp:Panel>
<asp:Panel ID="pnlLoggedin" runat="server">
     歡迎您,<asp:Label ID="lblUserName" runat="server"></asp:Label>!
     [<asp:LinkButton ID="btnLogout" runat="server" Text="註銷" 
         onclick="btnLogout_Click"></asp:LinkButton>]
</asp:Panel>
<asp:Panel ID="pnlNavigate" runat="server">
     <asp:HyperLink ID="lnkDefault" runat="server" NavigateUrl="~/default.aspx" Text="首頁">
     </asp:HyperLink> |
     <asp:HyperLink ID="lnkTest" runat="server" NavigateUrl="~/test.aspx" Text="測試頁">
     </asp:HyperLink>
</asp:Panel>

  這裏提供了三個Panel控件——pnlAnonymous、pnlLoggedin和pnlNavigate。pnlAnonymous用於在用戶未登錄時顯示“登錄”和“註冊”鏈接;pnlLoggedin用於在用戶已登錄時顯示用戶信息(如用戶名和到用戶個人信息頁的鏈接等,這裏僅顯示用戶名),以及一個“註銷”按鈕;pnlNavigate在任何時候都顯示,是站點的導航欄。

  現在我們要實現的是,判斷用戶是否登錄,並顯示pnlAnonymous和pnlLoggedin二者之一。這裏,如果是使用ASP.NET 2.0 Membership,則可以方便地使用LoginView、LoginName和LoginStatus等控件實現這些功能;然而我們不得不爲此忍受Membership所帶來的龐大而繁多的數據庫對象,或者花更多時間去編寫自定義的MembershipPorvider。

  這一系列的第一部分曾介紹過,如果用戶已經登錄,則可以從HttpContext.User.Identity.Name得到已登錄用戶的標識(通常是用戶名)。然而,如果用戶未登錄,這個值則爲空字符串。因此,通過判斷該值是否爲空字符串,即可的值用戶是否已登錄。

http://www.microsoft.com/china/msdn/msdnmvp/page8_1.html


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