共用方式為


建立使用者帳戶 (VB)

作者:Scott Mitchell

注意

自本文撰寫以來,ASP.NET 成員資格提供者已由 ASP.NET Identity 取代。 我們強烈建議更新應用程式以使用 ASP.NET Identity 平台,而不是撰寫本文時介紹的成員資格提供者。 與 ASP.NET 成員資格系統相比,ASP.NET Identity 具有許多優勢,包括:

  • 更好的效能
  • 改進的可擴展性和可測試性
  • 支援 OAuth、OpenID Connect 和雙重認證
  • 基於宣告的身分支援
  • 與 ASP.Net Core 更好的互通性

下載程式代碼下載 PDF

在本教學課程中,我們將探索使用成員資格架構 (透過 SqlMembershipProvider) 來建立新的用戶帳戶。 我們將瞭解如何以程序設計方式和透過 ASP 建立新的使用者。NET 的內建 CreateUserWizard 控件。

簡介

在上述教學課程中,我們已在資料庫中安裝應用程式服務架構,以新增 和SqlRoleProvider所需的SqlMembershipProvider數據表、檢視和預存程式。 這會建立本系列中其餘教學課程所需的基礎結構。 在本教學課程中,我們將探索使用成員資格架構 (透過 SqlMembershipProvider) 來建立新的用戶帳戶。 我們將瞭解如何以程序設計方式和透過 ASP 建立新的使用者。NET 的內建 CreateUserWizard 控件。

除了瞭解如何建立新的用戶帳戶之外,我們還需要更新我們在窗體驗證概觀教學課程中第一次建立的示範網站。 我們的示範 Web 應用程式具有登入頁面,可針對硬式編碼的使用者名稱/密碼組驗證用戶的認證。 此外, Global.asax 也包含為已驗證使用者建立自定義 IPrincipalIIdentity 物件的程序代碼。 我們將更新登入頁面,以根據成員資格架構驗證用戶的認證,並移除自定義主體和身分識別邏輯。

現在就開始吧!

窗體驗證和成員資格檢查清單

開始使用成員資格架構之前,讓我們花點時間檢閱我們達到此點所採取的重要步驟。 在表單型驗證案例中使用成員資格架構時 SqlMembershipProvider ,必須先執行下列步驟,才能在 Web 應用程式中實作成員資格功能:

  1. 啟用表單型驗證。 如我們在窗體驗證概觀中所討論,窗體驗證是藉由編輯Web.config和將元素的 mode 屬性設定<authentication>Forms來啟用。 啟用窗體驗證後,會檢查 每個傳入要求是否有窗體驗證票證,如果存在,則會識別要求者。
  2. 將應用程式服務架構新增至適當的資料庫。 使用 SqlMembershipProvider 時,我們需要將應用程式服務架構安裝到資料庫。 此架構通常會新增至保存應用程式數據模型的相同資料庫。 在 SQL Server 中建立成員資格架構教學課程探討如何使用 aspnet_regsql.exe 工具來達成此目的。
  3. 自訂 Web 應用程式的 [設定],以參考步驟 2 中的資料庫。SQL Server 中建立成員資格架構教學課程顯示兩種方式可設定 Web 應用程式,讓 SqlMembershipProvider 使用步驟 2:修改 LocalSqlServer 連接字串 名稱所選取的資料庫;或將新的已註冊提供者新增至成員資格架構提供者清單,以及自定義該新提供者以使用步驟 2 中的資料庫。

建置使用 SqlMembershipProvider 和 表單型驗證的 Web 應用程式時,您必須先執行這三個步驟,才能使用 Membership 類別或 ASP.NET 登入 Web 控制件。 由於我們已在先前的教學課程中執行這些步驟,因此我們已準備好開始使用成員資格架構!

步驟 1:新增 ASP.NET 頁面

在本教學課程和接下來的三個中,我們將檢查各種成員資格相關函式和功能。 我們需要一系列 ASP.NET 頁面,以實作這些教學課程中檢查的主題。 讓我們建立這些頁面,然後建立網站地圖檔案 (Web.sitemap)

先在專案中建立一個名為 Membership 的新資料夾。 接下來,將五個新的 ASP.NET 頁面新增至 Membership 資料夾,並將每個頁面與 Site.master 主版頁面連結。 將頁面命名為:

  • CreatingUserAccounts.aspx
  • UserBasedAuthorization.aspx
  • EnhancedCreateUserWizard.aspx
  • AdditionalUserInfo.aspx
  • Guestbook.aspx

此時,專案的 方案總管 看起來應該類似圖 1 所示的螢幕快照。

已將五個新頁面新增至成員資格資料夾

圖 1:已將五個新頁面新增至 Membership 資料夾 (按兩下以檢視完整大小的影像

此時,每個頁面都應該有兩個 Content 控件,一個用於主版頁面的 ContentPlaceHolders: MainContentLoginContent

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent"
Runat="Server"> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="LoginContent"
Runat="Server"> 
</asp:Content>

回想一 LoginContent 下,ContentPlaceHolder 的預設標記會顯示登入或註銷網站的鏈接,視使用者是否通過驗證而定。 不過,內容控制件的存在 Content2 會覆寫主版頁面的預設標記。 如我們在窗體驗證概觀教學課程中所討論,這在我們不想在左欄中顯示登入相關選項的頁面很有用。

不過,針對這五個頁面,我們想要顯示 ContentPlaceHolder 的主版頁面預設標記 LoginContent 。 因此,移除 Content 控件的 Content2 宣告式標記。 這麼做之後,五頁的標記中每個都應該只包含一個 Content 控件。

步驟 2:建立網站地圖

除了最微不足道的網站,還需要實作某種形式的導覽用戶介面。 瀏覽使用者介面可能是網站各區段連結的簡單清單。 或者,這些連結可以排列成功能表或樹檢視。 身為頁面開發人員,建立導覽使用者介面只是本文的一半。 我們也需要一些方法,以可維護且可更新的方式定義網站的邏輯結構。 當新增頁面或移除現有的頁面時,我們希望能夠更新單一來源 - 網站地圖 - 並讓這些修改反映在網站的瀏覽使用者介面上。

這兩項工作 -- 定義網站地圖,並根據網站地圖實作導覽使用者介面 -- 由於網站地圖架構和 ASP.NET 2.0 版中新增的導覽 Web 控件,很容易完成。 網站地圖架構可讓開發人員定義網站地圖,然後透過程式設計 API 存取網站地圖(類別SiteMap)。 內建的導覽 Web 控件包括 功能表控件TreeView 控件SiteMapPath 控制項

如同成員資格和角色架構,網站對應架構會建置在提供者模型之上。 網站地圖提供者類別的工作是從持續性數據存放區產生 類別所使用的 SiteMap 記憶體內部結構,例如 XML 檔案或資料庫數據表。 .NET Framework 隨附默認網站地圖提供者,可讀取 XML 檔案的網站地圖數據(XmlSiteMapProvider),而這是我們在本教學課程中將使用的提供者。 如需一些替代的網站地圖提供者實作,請參閱本教學課程結尾的一節。

默認的網站地圖提供者預期名為 Web.sitemap 的 XML 檔案會存在根目錄。 由於我們使用這個預設提供者,因此我們需要新增這類檔案,並以適當的 XML 格式定義網站地圖的結構。 若要新增檔案,請以滑鼠右鍵按兩下 方案總管 中的專案名稱,然後選擇[新增專案]。 從對話框中,選擇新增名為 Web.sitemap之網站地圖類型的檔案。

將名為 Web.sitemap 的檔案新增至專案的根目錄

圖 2:將名為 Web.sitemap 的檔案新增至專案的根目錄(按兩下以檢視完整大小的影像

XML 網站對應檔案會將網站的結構定義為階層。 這個階層式關聯性是透過元素的 <siteMapNode> 祖系,在 XML 檔案中建立模型。 Web.sitemap必須從具有一個<siteMap><siteMapNode>子系的父節點開始。 這個最上層 <siteMapNode> 元素代表階層的根目錄,而且可能會有任意數目的子代節點。 每個<siteMapNode>元素都必須包含屬性,而且可以選擇性地包含 urldescription 屬性;每個非空白url屬性都必須是唯一title的。

在檔案中 Web.sitemap 輸入下列 XML:

<?xml version="1.0" encoding="utf-8" ?> 
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"> 
 <siteMapNode url="~/Default.aspx" title="Home"> 
 <siteMapNode title="Membership">
 <siteMapNode url="~/Membership/CreatingUserAccounts.aspx" title="Creating User Accounts" /> 
 <siteMapNode url="~/Membership/UserBasedAuthorization.aspx" title="User-Based Authorization" /> 
 <siteMapNode url="~/Membership/Guestbook.aspx" title="Storing Additional User Information" /> 
 </siteMapNode> 
 </siteMapNode> 
</siteMap>

上述網站地圖標記會定義圖 3 中顯示的階層。

網站地圖代表階層式導覽結構

圖 3:網站地圖代表階層式導覽結構(按兩下以檢視完整大小的影像

步驟 3:更新主版頁面以包含導覽使用者介面

ASP.NET 包含一些用於設計使用者介面的導覽相關 Web 控制件。 其中包括 Menu、TreeView 和 SiteMapPath 控制件。 Menu 和 TreeView 控件會分別呈現功能表或樹狀結構中的網站地圖結構,而 SiteMapPath 會顯示階層連結,其中顯示正在流覽的目前節點及其上階。 網站地圖數據可以使用 SiteMapDataSource 系結至其他資料 Web 控制件,並可透過 類別以程式設計方式存取 SiteMap

由於網站地圖架構和導覽控件的徹底討論已超出本教學課程系列的範圍,而不是花時間製作我們自己的導覽使用者介面,而是借用我在 ASP.NET 2.0 教學課程系列中使用數據一個,該系列使用 Repeater 控件來顯示兩深的導覽連結清單, 如圖 4 所示。

若要建立此介面,請將下列宣告式標記新增至 Site.master 主版頁面的左側數據行,其中文字 TODO:功能表會移至這裡...目前位於 。

<ul> 
 <li> 
 <asp:HyperLink runat="server" ID="lnkHome" NavigateUrl="~/Default.aspx">Home</asp:HyperLink>
 </li> 
 <asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"> 
 <ItemTemplate>
 <li> 
 <asp:HyperLink ID="lnkMenuItem" runat="server" 
 NavigateUrl='<%# Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink>
 <asp:Repeater ID="submenu" runat="server" DataSource="<%# 
 CType(Container.DataItem, SiteMapNode).ChildNodes %>"> 
 <HeaderTemplate> 
 <ul> 
 </HeaderTemplate> 
 <ItemTemplate>
 <li> 
 <asp:HyperLink ID="lnkMenuItem" 
 runat="server" NavigateUrl='<%#  Eval("Url") %>'><%# Eval("Title") %></asp:HyperLink> 
 </li>
 </ItemTemplate> 
 <FooterTemplate> 
 </ul> 
 </FooterTemplate>
 </asp:Repeater> 
 </li> 
 </ItemTemplate> 
 </asp:Repeater> 
</ul>
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false"/>

上述標記會將名為 menu 的 Repeater 控制項系結至 SiteMapDataSource,此控件會傳回 中 Web.sitemap定義的網站地圖階層。 由於 SiteMapDataSource 控制件的 ShowStartingNode 屬性 設定為 False,因此會從 Home 節點的子代開始傳回網站地圖的階層。 Repeater 會在 元素中 <li> 顯示每個節點(目前只是成員資格)。 另一個內部 Repeater 接著會在巢狀的未排序列表中顯示目前節點的子系。

圖 4 顯示上述標記的轉譯輸出,其中包含我們在步驟 2 中建立的網站地圖結構。 Repeater 會轉譯 vanilla unordered list markup;中 Styles.css 定義的級聯樣式表單規則負責美觀的版面配置。 如需上述標記運作方式的更詳細描述,請參閱 主版頁面和網站導覽 教學課程。

導覽使用者介面是使用巢狀未排序列表轉譯

圖 4:使用巢狀未排序列表轉譯導覽使用者介面(按兩下以檢視完整大小的影像

新增階層連結流覽

除了左側數據行中的連結清單之外,我們也會讓每個頁面顯示 階層連結。 階層連結是瀏覽使用者介面元素,可快速向用戶顯示其站台階層中目前的位置。 SiteMapPath 控件會使用網站地圖架構來判斷網站地圖中目前頁面的位置,然後根據此資訊顯示階層連結。

具體來說,將專案新增 <span> 至主版頁面的標頭 <div> 元素,並將新 <span> 元素的 class 屬性設定為階層連結。 (類別 Styles.css 包含階層連結類別的規則。)接下來,將 SiteMapPath 新增至這個新 <span> 元素。

<div id="header"> 
 <span class="title">User Account Tutorials</span><br /> 
 <span class="breadcrumb"> 
 <asp:SiteMapPath ID="SiteMapPath1" runat="server"> 
 </asp:SiteMapPath> 
 </span> 
</div>

圖 5 顯示造訪 ~/Membership/CreatingUserAccounts.aspx時 SiteMapPath 的輸出。

階層連結會顯示網站地圖中的目前頁面及其上階

圖 5:階層連結顯示網站地圖中的目前頁面及其上階 (按兩下以檢視完整大小的影像

步驟 4:移除自定義主體和身分識別邏輯

自訂主體和身分識別物件可以與已驗證的使用者相關聯。 我們藉由為應用程式的 PostAuthenticateRequest 事件建立 事件處理程式Global.asax來完成這項作業,在驗證用戶之後FormsAuthenticationModule引發。 在此事件處理程式中,我們將 所新增FormsAuthenticationModule的 和 FormsIdentity 物件取代GenericPrincipal為我們在該教學課程中建立的 CustomPrincipalCustomIdentity 物件。

雖然自定義主體和身分識別物件在某些案例中很有用,但在大多數情況下 GenericPrincipal ,和 FormsIdentity 物件就已足夠。 因此,我認為回到默認行為是值得的。 藉由移除或批注 PostAuthenticateRequest 事件處理程式或完全刪除 Global.asax 檔案,來進行這項變更。

注意

在中Global.asax批註或移除程式代碼之後,您必須將屬性轉換成 User.Identity CustomIdentity 實例的程式代碼後置類別中的Default.aspx's程式代碼批注化。

步驟 5:以程序設計方式建立新使用者

若要透過成員資格架構建立新的用戶帳戶,請使用 Membership 類別的 CreateUser 方法。 此方法具有使用者名稱、密碼和其他使用者相關欄位的輸入參數。 在叫用時,它會將新用戶帳戶的建立委派給已設定的成員資格提供者,然後傳 MembershipUser 回代表剛建立之用戶帳戶的物件

方法 CreateUser 有四個多載,每個多載都接受不同的輸入參數數目:

這四個多載在收集的資訊量上有所不同。 例如,第一個多載只需要新用戶帳戶的使用者名稱和密碼,而第二個多載也需要使用者的電子郵件位址。

這些多載存在,因為建立新用戶帳戶所需的信息取決於成員資格提供者的組態設定。 在 SQL Server 中建立成員資格架構教學課程中,我們檢查了在 中Web.config指定成員資格提供者組態設定。 表 2 包含組態設定的完整清單。

其中一個這類成員資格提供者組態設定會影響可能使用多 CreateUser 載的設定是 requiresQuestionAndAnswer 設定。 如果 requiresQuestionAndAnswer 設定為 true (預設值),則在建立新的用戶帳戶時,我們必須指定安全性問題和答案。 如果使用者需要重設或變更其密碼,稍後會使用此資訊。 具體而言,此時會顯示安全性問題,而且必須輸入正確的答案,才能重設或變更其密碼。 因此,如果 requiresQuestionAndAnswer 設定為 true ,則呼叫前兩 CreateUser 個多載的其中一個會導致例外狀況,因為安全性問題和答案遺失。 由於應用程式目前已設定為需要安全性問題和解答,因此在以程序設計方式建立使用者時,我們需要使用后兩個多載的其中一個。

為了說明如何使用 CreateUser 方法,讓我們建立使用者介面,並在其中提示使用者輸入其名稱、密碼、電子郵件,以及預先定義的安全性問題的解答。 CreatingUserAccounts.aspx開啟資料夾中的頁面,Membership並將下列 Web 控制項新增至內容控制項:

  • 名為的 TextBox Username
  • 名為 Password的 TextBox,其 TextMode 屬性設定為 Password
  • 名為的 TextBox Email
  • 已清除名為 且其Text屬性為SecurityQuestion的標籤
  • 名為的 TextBox SecurityAnswer
  • 名為 CreateAccountButton 的按鈕,其 Text 屬性設定為 [建立使用者帳戶]
  • 已清除其Text屬性且名為 CreateAccountResults 的標籤

此時,您的畫面看起來應該類似圖 6 所示的螢幕快照。

將各種 Web 控制項新增至 CreatingUserAccounts.aspx 頁面

圖 6:將各種 Web 控制項新增至 CreatingUserAccounts.aspx Page按兩下以檢視完整大小的影像

Label SecurityQuestionSecurityAnswer TextBox 旨在顯示預先定義的安全性問題,並收集使用者的答案。 請注意,安全性問題和答案都是以用戶為基礎來儲存,因此可以允許每個用戶定義自己的安全性問題。 不過,在此範例中,我決定使用通用安全性問題,也就是:您最愛的色彩為何?

若要實作這個預先定義的安全性問題,請將常數新增至名為的頁面程序代碼後置類別 passwordQuestion,併為其指派安全性問題。 然後,在事件處理程式中 Page_Load ,將此常數指派給 SecurityQuestion Label 的 Text 屬性:

Const passwordQuestion As String = "What is your favorite color"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
 If Not Page.IsPostBack Then 
 SecurityQuestion.Text = passwordQuestion 
 End If 
End Sub

接下來,為 CreateAccountButton'Click 事件建立事件處理常式,並新增以下程式碼:

Protected Sub CreateAccountButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles CreateAccountButton.Click 
 Dim createStatus As MembershipCreateStatus 
 Dim newUser As MembershipUser = _ 
 Membership.CreateUser(Username.Text, Password.Text, _ 
 Email.Text, passwordQuestion, _ 
 SecurityAnswer.Text, True, _ 
 createStatus)
 Select Case createStatus 
 Case MembershipCreateStatus.Success 
 CreateAccountResults.Text = "The user account was successfully created!" 
 Case MembershipCreateStatus.DuplicateUserName 
 CreateAccountResults.Text = "There already exists a user with this username." 
 Case MembershipCreateStatus.DuplicateEmail 
 CreateAccountResults.Text = "There already exists a user with this email address." 
 Case MembershipCreateStatus.InvalidEmail
 CreateAccountResults.Text = "There email address you provided in invalid." 
 Case MembershipCreateStatus.InvalidAnswer 
 CreateAccountResults.Text = "There security answer was invalid." 
 Case MembershipCreateStatus.InvalidPassword 
 CreateAccountResults.Text = "The password you provided is invalid. It must be seven characters long and have at least one non-alphanumeric character." 
 Case Else 
 CreateAccountResults.Text = "There was an unknown error; the user account was NOT created."
 End Select 
End Sub

Click事件處理程式一開始會定義 名為 createStatus MembershipCreateStatus的變數。 MembershipCreateStatus 是列舉,表示作業的狀態 CreateUser 。 例如,如果成功建立用戶帳戶,則產生的 MembershipCreateStatus 實例會設定為的值,另一 Success; 方面,如果作業失敗,因為已經有具有相同使用者名稱的使用者,則會將它設定為的值 DuplicateUserName。 在我們使用的多載中 CreateUser ,我們需要將 MembershipCreateStatus 實例傳遞至 方法。 此參數設定為 方法內 CreateUser 的適當值,我們可以在方法呼叫之後檢查其值,以判斷用戶帳戶是否已成功建立。

在呼叫 CreateUser之後,傳入 createStatus時, Select Case 語句會根據指派給 createStatus的值來輸出適當的訊息。 圖 7 顯示新使用者成功建立時的輸出。 圖 8 和 9 顯示未建立使用者帳戶時的輸出。 在圖 8 中,訪客輸入了五個字母的密碼,不符合成員資格提供者組態設定中說明的密碼強度需求。 在圖 9 中,訪客嘗試建立具有現有使用者名稱的用戶帳戶(圖 7 中建立的用戶名稱)。

已成功建立新的用戶帳戶

圖 7:已成功建立新的使用者帳戶(單擊以檢視完整大小的映射

未建立用戶帳戶,因為提供的密碼太弱

圖 8:未建立使用者帳戶,因為提供的密碼太弱(按兩下以檢視完整大小的影像

未建立使用者帳戶,因為用戶名稱已在使用中

圖 9:未建立使用者帳戶,因為使用者名稱已在使用中(按兩下以檢視完整大小的影像

注意

您可能想知道在使用前兩 CreateUser 個方法多載的其中一個時,如何判斷成功或失敗,兩者都沒有 類型的 MembershipCreateStatus參數。 這前兩個MembershipCreateUserException多載會在發生失敗時擲回例外狀況,其中包含 StatusCode 類型的MembershipCreateStatus屬性

建立一些使用者帳戶之後,請列出 資料庫中 的和 aspnet_Membership 數據表SecurityTutorials.mdf內容aspnet_Users,確認帳戶已建立。 如圖 10 所示,我已透過 CreatingUserAccounts.aspx 頁面新增兩個使用者:Tito 和 Bruce。

成員資格使用者存放區中有兩個使用者:Tito 和 Bruce

圖 10:成員資格使用者存放區中有兩個使用者:Tito 和 Bruce (按兩下以檢視完整大小的影像

雖然成員資格使用者存放區現在包含 Bruce 和 Tito 的帳戶資訊,但我們尚未實作可讓 Bruce 或 Tito 登入網站的功能。 目前,Login.aspx會根據一組硬式編碼的使用者名稱/密碼組來驗證用戶的認證-它不會針對成員資格架構驗證提供的認證。 現在,在和 aspnet_Membership 數據表中看到aspnet_Users新的用戶帳戶必須足夠。 在下一個教學課程中, 針對成員資格使用者存放區驗證使用者認證,我們將更新登入頁面,以驗證成員資格存放區。

注意

如果您沒有在資料庫中看到任何使用者 SecurityTutorials.mdf ,可能是因為 Web 應用程式使用預設成員資格提供者, AspNetSqlMembershipProvider而該提供者會使用 ASPNETDB.mdf 資料庫作為其使用者存放區。 若要判斷此問題是否為問題,請按兩下 方案總管 中的 [重新整理] 按鈕。 如果名為 ASPNETDB.mdf 的資料庫已新增至 App_Data 資料夾,這就是問題。 返回在 SQL Server 中建立成員資格架構教學課程的步驟 4,以取得如何正確設定成員資格提供者的指示。

在大部分的建立用戶帳戶案例中,訪客會顯示一些介面,以輸入其使用者名稱、密碼、電子郵件和其他基本資訊,此時會建立新的帳戶。 在此步驟中,我們查看了手動建置這類介面,然後瞭解如何使用 Membership.CreateUser 方法來根據用戶的輸入,以程序設計方式新增新的用戶帳戶。 不過,我們的程式代碼剛建立新的用戶帳戶。 它未執行任何後續動作,例如在剛剛建立的用戶帳戶下登入網站,或傳送確認電子郵件給使用者。 這些額外的步驟需要 Button Click 事件處理程式中的其他程式代碼。

ASP.NET 隨附 CreateUserWizard 控件,其設計目的是要處理用戶帳戶建立程式,從轉譯使用者介面以建立新的用戶帳戶、在成員資格架構中建立帳戶,以及執行帳戶後建立工作,例如傳送確認電子郵件,並將剛建立的用戶記錄到網站。 使用 CreateUserWizard 控制項就像將 CreateUserWizard 控制件從工具箱拖曳到頁面一樣簡單,然後設定幾個屬性。 在大部分情況下,您不需要撰寫單行程序代碼。 我們將在步驟 6 中詳細探索此巧妙的控件。

如果只有透過一般建立帳戶網頁建立新的用戶帳戶,您就不太可能需要撰寫使用 CreateUser 方法的程式代碼,因為 CreateUserWizard 控制項可能會符合您的需求。 不過,當您需要高度自定義的建立帳戶用戶體驗,或需要透過替代介面以程序設計方式建立新的用戶帳戶時, CreateUser 此方法就很方便。 例如,您可能有一個頁面,可讓使用者上傳包含來自其他應用程式之使用者資訊的 XML 檔案。 頁面可能會剖析上傳的 XML 檔案內容,並藉由呼叫 CreateUser 方法,為 XML 中代表的每個使用者建立新的帳戶。

步驟 6:使用 CreateUserWizard 控件建立新使用者

ASP.NET 隨附許多登入 Web 控制件。 這些控件可協助許多常見的用戶帳戶和登入相關案例。 CreateUserWizard 控件是一個這類控件,其設計目的是要呈現將新用戶帳戶新增至 Membership 架構的用戶介面。

如同其他許多與 Login 相關的 Web 控制件,CreateUserWizard 不需要撰寫單行程式代碼即可使用。 它會根據成員資格提供者的組態設定提供使用者介面,並在使用者輸入必要資訊后,於內部呼叫 Membership 類別 CreateUser 的方法,然後按兩下 [建立使用者] 按鈕。 CreateUserWizard 控件非常可自定義。 帳戶建立程式的各個階段都會引發許多事件。 我們可以視需要建立事件處理程式,在帳戶建立工作流程中插入自定義邏輯。 此外,CreateUserWizard 的外觀非常靈活。 有一些屬性可定義預設介面的外觀;如有必要,控件可以轉換成範本,也可以新增額外的用戶註冊步驟。

讓我們從使用 CreateUserWizard 控件的預設介面和行為開始。 然後,我們將探索如何透過控件的屬性和事件來自定義外觀。

檢查 CreateUserWizard 的預設介面和行為

CreatingUserAccounts.aspx返回資料夾中的頁面Membership,切換至 [設計] 或 [分割] 模式,然後將 CreateUserWizard 控件新增至頁面頂端。 CreateUserWizard 控制者會在 [工具箱的登入控件] 區段下提交。 新增 控制項之後,將其 ID 屬性設定為 RegisterUser。 如圖 11 所示的螢幕快照,CreateUserWizard 會轉譯具有新使用者使用者名稱、密碼、電子郵件地址和安全性問題和解答文字框的介面。

CreateUserWizard 控件會轉譯一般建立使用者介面

圖 11:CreateUserWizard 控件轉譯一般建立使用者介面 (按兩下以檢視完整大小的影像

讓我們花點時間比較 CreateUserWizard 控件所產生的預設使用者介面,以及我們在步驟 5 中建立的介面。 對於入門,CreateUserWizard 控件可讓訪客同時指定安全性問題和答案,而我們手動建立的介面則使用預先定義的安全性問題。 CreateUserWizard 控件的介面也包含驗證控件,但我們尚未在介面的表單域上實作驗證。 CreateUserWizard 控件介面包含 [確認密碼] 文本框(以及 CompareValidator,以確保輸入 [密碼] 和 [比較密碼] 文本框的文字相等)。

有趣的是,CreateUserWizard 控件會在轉譯其使用者介面時參考成員資格提供者的組態設定。 例如,只有在 設定為 True 時 requiresQuestionAndAnswer ,才會顯示安全性問題和答案文本框。 同樣地,CreateUserWizard 會自動新增 RegularExpressionValidator 控件,以確保符合密碼強度需求,並根據 、 和 組態設定來設定其 ErrorMessageValidationExpression passwordStrengthRegularExpression 屬性minRequiredPasswordLengthminRequiredNonalphanumericCharacters

CreateUserWizard 控件,如其名稱所示,衍生自 Wizard控件。 精靈控件的設計目的是提供完成多步驟工作的介面。 精靈控件可能有任意數目 WizardSteps的,每個控件都是定義該步驟之 HTML 和 Web 控件的範本。 精靈控件一開始會顯示第一 WizardStep個,以及允許使用者從一個步驟繼續進行或返回先前步驟的導覽控件。

如圖 11 所示的宣告式標記,CreateUserWizard 控件的預設介面包含兩個 WizardStep

  • CreateUserWizardStep ? 會轉譯 介面,以收集用來建立新用戶帳戶的資訊。 這是圖 11 中顯示的步驟。
  • CompleteWizardStep ? 會轉譯訊息,指出已成功建立帳戶。

CreateUserWizard 的外觀和行為可以藉由將這些步驟之一轉換為範本,或藉由新增您自己的 WizardStep 來修改。 我們將在儲存其他使用者資訊教學課程中,將 新增 WizardStep 至註冊介面。

讓我們看看 CreateUserWizard 控件的運作情形。 CreatingUserAccounts.aspx透過瀏覽器瀏覽頁面。 首先,在 CreateUserWizard 的介面中輸入一些無效的值。 請嘗試輸入不符合密碼強度需求的密碼,或將 [用戶名稱] 文本框保留空白。 CreateUserWizard 會顯示適當的錯誤訊息。 圖 12 顯示嘗試建立密碼不足的使用者時的輸出。

CreateUserWizard 自動插入驗證控件

圖 12:CreateUserWizard 自動插入驗證控件 (按一下以檢視完整大小的影像

接下來,在 CreateUserWizard 中輸入適當的值,然後按兩下 [建立使用者] 按鈕。 假設已輸入必要的欄位且密碼強度已足夠,CreateUserWizard 會透過成員資格架構建立新的使用者帳戶,然後顯示 CompleteWizardStep的介面(請參閱圖 13)。 在幕後,CreateUserWizard 會呼叫 Membership.CreateUser 方法,就像我們在步驟 5 中所做的一樣。

已成功建立新的用戶帳戶

圖 13:已成功建立新的使用者帳戶(單擊以檢視完整大小的影像

注意

如圖 13 所示, CompleteWizardStep的 介面包含 [繼續] 按鈕。 不過,此時按兩下只會執行回傳,讓訪客留在相同的頁面上。 在自定義 CreateUserWizard 的外觀和行為透過其屬性一節中,我們將探討如何讓此按鈕將訪客傳送至 Default.aspx (或其他頁面)。

建立新的使用者帳戶之後,返回 Visual Studio 並檢查aspnet_Usersaspnet_Membership和數據表,就像我們在圖 10 中所做的一樣,確認帳戶已成功建立。

透過其屬性自定義 CreateUserWizard 的行為和外觀

您可以透過屬性、 WizardStep s 和事件處理程式,以各種方式自定義 CreateUserWizard。 在本節中,我們將探討如何透過控件的屬性來自定義控件的外觀;下一節將探討透過事件處理程式擴充控件的行為。

幾乎所有顯示在 CreateUserWizard 控件的預設使用者介面中的文字,都可以透過其大量的屬性來自定義。 例如,使用者名稱、密碼、確認密碼、電子郵件、安全性問題和安全性回應卷標會顯示在文本框左邊,可以分別由 UserNameLabelTextPasswordLabelTextConfirmPasswordLabelTextEmailLabelTextQuestionLabelTextAnswerLabelText 屬性自定義。 同樣地,也有屬性可指定 和 CompleteWizardStepCreateUserWizardStep [建立使用者] 和 [繼續] 按鈕的文字,以及這些按鈕是否呈現為 Buttons、LinkButtons 或 ImageButtons。

色彩、框線、字型和其他視覺元素可透過許多樣式屬性來設定。 CreateUserWizard 控件本身具有通用的 Web 控件樣式屬性 - BackColorBorderStyleCssClassFont等,而且有一些樣式屬性可定義 CreateUserWizard 介面特定區段的外觀。 例如,屬性TextBoxStyle會定義 中CreateUserWizardStep文本框的樣式,而 TitleTextStyle 屬性會定義標題的樣式(註冊新帳戶)。

除了外觀相關屬性之外,還有一些會影響 CreateUserWizard 控件行為的屬性。 如果設定為 True,則 DisplayCancelButton 屬性會顯示 [建立使用者] 按鈕旁的 [取消] 按鈕(預設值為 False)。 如果您顯示 [取消] 按鈕,請務必也設定 CancelDestinationPageUrl 屬性,這會指定使用者在按兩下 [取消] 之後傳送至的頁面。 如上一節所述,介面中的 CompleteWizardStep[繼續] 按鈕會造成回傳,但讓訪客留在相同的頁面上。 若要在單擊 [繼續] 按鈕之後,將訪客傳送至其他頁面,只要在 屬性ContinueDestinationPageUrl指定 URL 即可。

讓我們更新 RegisterUser CreateUserWizard 控制項以顯示 [取消] 按鈕,並在按兩下 [取消] 或 [繼續] 按鈕時將訪客傳送至 Default.aspx 。 若要達成此目的,請將 DisplayCancelButton 屬性設定為 True,並將 CancelDestinationPageUrlContinueDestinationPageUrl 屬性設定為 ~/Default.aspx。 圖 14 顯示透過瀏覽器檢視時更新的 CreateUserWizard。

CreateUserWizardStep 包含取消按鈕

圖 14CreateUserWizardStep 包含 [取消] 按鈕 (按兩下以檢視完整大小的影像

當訪客輸入使用者名稱、密碼、電子郵件地址和安全性問題和答案,然後按兩下 [建立使用者] 時,會建立新的用戶帳戶,且訪客會以新建立的使用者身分登入。 假設造訪頁面的人員正在為自己建立新的帳戶,這可能是想要的行為。 不過,您可能想要允許系統管理員新增用戶帳戶。 如此一來,就會建立用戶帳戶,但系統管理員仍會以系統管理員身分登入(而不是新建立的帳戶)。 此行為可以透過布爾 LoginCreatedUser 值屬性修改。

成員資格架構中的用戶帳戶包含已核准的旗標;未核准的用戶無法登入網站。 根據預設,新建立的帳戶會標示為已核准,讓用戶能夠立即登入網站。 不過,有可能讓新的使用者帳戶標示為未核准。 或許您希望系統管理員手動核准新使用者,才能登入;或者,您可能想要確認在註冊時輸入的電子郵件地址在允許使用者登入之前是否有效。 無論情況如何,您可以將 CreateUserWizard 控件的 DisableCreatedUser 屬性 設定為 True,讓新建立的使用者帳戶標示為未核准(預設值為 False)。

附註的其他行為相關屬性包括 AutoGeneratePasswordMailDefinitionAutoGeneratePassword如果屬性設定為 True,CreateUserWizardStep則 不會顯示 [密碼] 和 [確認密碼] 文本框;而是使用 Membership 類別GeneratePassword的 方法自動產生新建立的用戶密碼。 方法 GeneratePassword 會建構指定長度的密碼,且具有足夠數目的非英數位元,以滿足設定的密碼強度需求。

如果您想要將電子郵件傳送至帳戶建立程式期間指定的電子郵件地址,這個 MailDefinition 屬性 會很有用。 屬性 MailDefinition 包含一系列子屬性,用於定義建構的電子郵件訊息相關信息。 這些子屬性包括、PriorityIsBodyHtmlFrom、、 CCBodyFileNameSubject選項。 屬性BodyFileName會指向包含電子郵件訊息本文的文字或 HTML 檔案。 本文支援兩個預先定義的佔位元: <%UserName%><%Password%>。 如果存在於檔案中 BodyFileName ,這些佔位元將會取代為剛建立的使用者名稱和密碼。

注意

控件 CreateUserWizardMailDefinition 屬性只會指定建立新帳戶時所傳送之電子郵件訊息的詳細數據。 它不包含電子郵件訊息實際傳送方式的任何詳細資料(也就是是否使用 SMTP 伺服器或郵件投遞目錄、任何驗證資訊等等)。 這些低階詳細數據必須在中的 Web.config區段中定義<system.net>。 如需這些組態設定的詳細資訊,以及一般從 ASP.NET 2.0 傳送電子郵件的詳細資訊,請參閱 SystemNetMail.com 和我的文章: ASP.NET 2.0 傳送電子郵件的常見問題。

使用事件處理程式擴充 CreateUserWizard 的行為

CreateUserWizard 控件在其工作流程期間會引發一些事件。 例如,在訪客輸入其使用者名稱、密碼和其他相關信息,然後按兩下 [建立使用者] 按鈕之後,CreateUserWizard 控件會引發其 CreatingUser 事件。 如果在建立程式期間發生問題, CreateUserError 就會引發事件 ;不過,如果成功建立使用者,則會 CreatedUser 引發事件 。 還有其他 CreateUserWizard 控件事件會引發,但這些事件是最德式的三個。

在某些情況下,我們可能會想要點選 CreateUserWizard 工作流程,我們可以藉由為適當的事件建立事件處理程式來執行此動作。 為了說明這一點,讓我們增強 RegisterUser CreateUserWizard 控件,以在使用者名稱和密碼中包含一些自定義驗證。 特別是,讓我們增強 CreateUserWizard,讓使用者名稱不能包含前置或尾端空格,而且用戶名稱不能出現在密碼中的任何位置。 簡言之,我們想要防止有人建立像是 「Scott」 的用戶名稱,或擁有斯科特和 Scott.1234 等使用者名稱/密碼組合。

為了達成此目的,我們將建立 CreatingUser 事件的事件處理程式,以執行額外的驗證檢查。 如果提供的數據無效,我們需要取消建立程式。 我們也必須將標籤 Web 控制項新增至頁面,以顯示說明使用者名稱或密碼無效的訊息。 從在 CreateUserWizard 控制項底下新增 Label 控制元件開始,將其 ID 屬性設定為 InvalidUserNameOrPasswordMessage ,並將其 ForeColor 屬性設定為 Red。 清除其 Text 屬性,並將其 和 Visible 屬性設定EnableViewState為 False。

<asp:Label runat="server"" id="InvalidUserNameOrPasswordMessage"
 Visible="false" ForeColor="Red" EnableViewState="false"> 
</asp:Label>

接下來,建立 CreateUserWizard 控件事件的 CreatingUser 事件處理程式。 若要建立事件處理程式,請選取設計工具中的控件,然後移至 屬性視窗。 從該處按兩下閃電圖示,然後按兩下適當的事件來建立事件處理程式。

將下列程式碼加入至 CreatingUser 事件處理常式:

Protected Sub RegisterUser_CreatingUser(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.LoginCancelEventArgs) Handles RegisterUser.CreatingUser
 Dim trimmedUserName As String = RegisterUser.UserName.Trim() 
 If RegisterUser.UserName.Length <> trimmedUserName.Length Then 
 ' Show the error message 
 InvalidUserNameOrPasswordMessage.Text = "The username cannot contain leading or trailing spaces." 
 InvalidUserNameOrPasswordMessage.Visible = True 
 ' Cancel the create user workflow 
 e.Cancel = True 
 Else 
 ' Username is valid, make sure that the password does not contain the username 
 If RegisterUser.Password.IndexOf(RegisterUser.UserName, StringComparison.OrdinalIgnoreCase) >= 0 Then 
 ' Show the error message 
 InvalidUserNameOrPasswordMessage.Text = "The username may not appear anywhere in the password." 
 InvalidUserNameOrPasswordMessage.Visible = True 
 ' Cancel the create user workflow 
 e.Cancel = True 
 End If 
 End If 
End Sub

請注意,輸入 CreateUserWizard 控件的使用者名稱和密碼可透過其 UserNamePassword 屬性分別取得。 我們會在上述事件處理程式中使用這些屬性來判斷提供的用戶名稱是否包含前置或尾端空格,以及用戶名稱是否在密碼內找到。 如果符合上述任一條件,則標籤中 InvalidUserNameOrPasswordMessage 會顯示錯誤訊息,而事件處理程式的 e.Cancel 屬性會設定為 True。 如果 e.Cancel 設定為 True,則 CreateUserWizard 會縮短其工作流程,有效地取消使用者帳戶建立程式。

圖 15 顯示當使用者輸入具有前置空格的用戶名稱時,的螢幕快照 CreatingUserAccounts.aspx

不允許具有前置或尾端空格的用戶名稱

圖 15:不允許具有前置或尾端空格的使用者名稱(單擊以檢視完整大小的影像

注意

我們將在儲存其他使用者資訊教學課程中看到使用 CreateUserWizard 控件事件的CreatedUser範例。

摘要

類別 MembershipCreateUser 方法會在 Membership 架構中建立新的用戶帳戶。 其方式是將呼叫委派給已設定的成員資格提供者。 在的案例中 SqlMembershipProviderCreateUser 方法會將記錄新增至 aspnet_Usersaspnet_Membership 資料庫數據表。

雖然可以程序設計方式建立新的用戶帳戶(如我們在步驟 5 中所見),但使用 CreateUserWizard 控制件的更快且更簡單的方法。 此控件會轉譯多步驟使用者介面,以收集用戶資訊,並在成員資格架構中建立新的使用者。 實際上,此控件會使用與步驟 5 中檢查相同的 Membership.CreateUser 方法,但控件會建立使用者介面、驗證控件,並回應用戶帳戶建立錯誤,而不需要撰寫程式代碼。

此時,我們已有建立新用戶帳戶的功能。 不過,登入頁面仍會針對我們在第二個教學課程中指定的硬式編碼認證進行驗證。 在下一個教學課程中,我們將更新Login.aspx,以針對成員資格架構驗證使用者提供的認證。

快樂程式!

深入閱讀

有關本教學課程中討論的主題的更多資訊,請參閱以下資源:

關於作者

斯科特·米切爾,多個 ASP/ASP.NET 書籍的作者,4GuysFromRolla.com 的創始人,自1998年以來一直與Microsoft Web 技術合作。 Scott 擔任獨立顧問、講師和作家。 他的新書是 Sams Teach Yourself ASP.NET 2.0 in 24 Hours。 斯科特可以透過 mitchell@4guysfromrolla.com 他在的部落格聯繫到或通過他的博客 http://ScottOnWriting.NET

特別感謝

本教學系列得到了許多有用的審閱者的審閱。 本教學的首席審閱者是 Teresa Murphy。 有興趣查看我即將發表的 MSDN 文章嗎? 如果是這樣,請留言給我 mitchell@4GuysFromRolla.com