針對成員資格使用者存放區驗證使用者認證 (VB)
注意
自本文撰寫以來,ASP.NET 成員資格提供者已被 ASP.NET 身分識別取代。 強烈建議您更新應用程式以使用 ASP.NET 身分識別 平臺,而不是本文撰寫時精選的成員資格提供者。 ASP.NET 身分識別對於 ASP.NET 成員資格系統有一些優點,包括 :
- 更好的效能
- 改善擴充性和可測試性
- 支援 OAuth、OpenID Connect 和雙因素驗證
- 宣告型身分識別支援
- 與 ASP.Net Core 更好的互通性
在本教學課程中,我們將檢查如何使用程式設計方式和登入控制項,針對成員資格使用者存放區驗證使用者的認證。 我們也將探討如何自訂登入控制項的外觀和行為。
簡介
在上述教學 課程中,我們已瞭解如何在成員資格架構中建立新的使用者帳戶。 我們先透過 類別的 CreateUser
方法以程式設計方式建立使用者帳戶 Membership
,然後使用 CreateUserWizard Web 控制項來檢查。 不過,登入頁面目前會根據使用者名稱和密碼組的硬式編碼清單來驗證提供的認證。 我們需要更新登入頁面的邏輯,以便針對成員資格架構的使用者存放區驗證認證。
就像建立使用者帳戶一樣,認證可以透過程式設計或宣告方式進行驗證。 成員資格 API 包含一種方法,以程式設計方式驗證使用者對使用者存放區的認證。 而且 ASP.NET 隨附登入 Web 控制項,其會轉譯使用者介面,其中包含使用者名稱和密碼的文字方塊,以及要登入的按鈕。
在本教學課程中,我們將檢查如何使用程式設計方式和登入控制項,針對成員資格使用者存放區驗證使用者的認證。 我們也將探討如何自訂登入控制項的外觀和行為。 現在就開始吧!
步驟 1:針對成員資格使用者存放區驗證認證
對於使用表單驗證的網站,使用者會造訪登入頁面並輸入其認證,以登入網站。 然後,這些認證會與使用者存放區進行比較。 如果他們有效,則會將表單驗證票證授與使用者,這是表示訪客身分識別和真確性的安全性權杖。
若要根據 Membership 架構驗證使用者,請使用 Membership
類別的ValidateUser
方法。 方法 ValidateUser
會接受兩個輸入參數 - username
和 password
-,並傳回布林值,指出認證是否有效。 如同我們在 CreateUser
上一個教學課程中檢查的方法,方法會將 ValidateUser
實際驗證委派給已設定的成員資格提供者。
會 SqlMembershipProvider
透過 aspnet_Membership_GetPasswordWithFormat
預存程式取得指定的使用者密碼,以驗證提供的認證。 回想一下,會 SqlMembershipProvider
使用下列三種格式之一來儲存使用者的密碼:清除、加密或雜湊。 預 aspnet_Membership_GetPasswordWithFormat
存程式會以原始格式傳回密碼。 針對加密或雜湊密碼,會將 SqlMembershipProvider
傳遞至 ValidateUser
方法的值轉換成 password
其相等的加密或雜湊狀態,然後將它與從資料庫傳回的內容進行比較。 如果儲存在資料庫中的密碼符合使用者輸入的格式密碼,則認證有效。
讓我們更新登入頁面 (~/ Login.aspx
) ,以便針對成員資格架構使用者存放區驗證提供的認證。 我們已在表單驗證概觀教學課程中 重新建立此登入頁面,建立具有兩個 TextBox 的介面作為使用者名稱和密碼、[記住我] 核取方塊,以及 [登入] 按鈕 (請參閱圖 1) 。 此程式碼會根據硬式編碼的使用者名稱和密碼組清單來驗證輸入的認證, (Scott/password、Jisun/password 和 Sam/password) 。
圖 1:登入頁面的介面包含兩個 TextBox、CheckBoxList 和 Button (Click 來檢視完整大小的影像)
登入頁面的使用者介面可以保持不變,但我們需要以程式碼取代登入按鈕的 Click
事件處理常式,以驗證使用者對成員資格架構使用者存放區的使用者。 更新事件處理常式,使其程式碼如下所示:
Protected Sub LoginButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LoginButton.Click
' Validate the user against the Membership framework user store
If Membership.ValidateUser(UserName.Text, Password.Text) Then
' Log the user into the site
FormsAuthentication.RedirectFromLoginPage(UserName.Text, RememberMe.Checked)
End If
' If we reach here, the user's credentials were invalid
InvalidCredentialsMessage.Visible = True
End Sub
此程式碼相當簡單。 我們一開始會呼叫 Membership.ValidateUser
方法,並傳入提供的使用者名稱和密碼。 如果該方法傳回 True,則使用者會透過 FormsAuthentication
類別的 RedirectFromLoginPage 方法登入網站。 (如我們在表單驗證概觀教學課程中所 討論,會 FormsAuthentication.RedirectFromLoginPage
建立表單驗證票證,然後將使用者重新導向至適當的頁面。) 如果認證無效, InvalidCredentialsMessage
則會顯示標籤,告知使用者使用者使用者名稱或密碼不正確。
就是這麼簡單!
若要測試登入頁面如預期般運作,請嘗試使用您在上一個教學課程中建立的其中一個使用者帳戶登入。 或者,如果您尚未建立帳戶,請繼續從 ~/Membership/CreatingUserAccounts.aspx
頁面建立帳戶。
注意
當使用者輸入其認證並提交登入頁面表單時,認證會以 純文字透過網際網路傳輸至網頁伺服器。 這表示任何駭客探查網路流量都可以看到使用者名稱和密碼。 若要避免這種情況,請務必使用 安全通訊端層 (SSL) 加密網路流量。 這可確保認證 (以及整個頁面的 HTML 標籤) 在離開瀏覽器之前加密,直到網頁伺服器收到這些認證為止。
成員資格架構如何處理不正確登入嘗試
當訪客到達登入頁面並提交其認證時,其瀏覽器會對登入頁面提出 HTTP 要求。 如果認證有效,HTTP 回應會在 Cookie 中包含驗證票證。 因此,嘗試入侵您的網站的駭客可能會建立一個程式,以詳盡地將 HTTP 要求傳送至具有有效使用者名稱和密碼猜測的登入頁面。 如果密碼猜測正確,登入頁面會傳回驗證票證 Cookie,此時程式知道它已輪轉為有效的使用者名稱/密碼組。 透過暴力密碼破解,這類程式可能會輪轉使用者的密碼,特別是當密碼很弱時。
為防止這類暴力密碼破解攻擊,成員資格架構會在特定時段內有特定數目失敗的登入嘗試,鎖定使用者。 確切的參數可透過下列兩個成員資格提供者組態設定來設定:
maxInvalidPasswordAttempts
- 指定在帳戶鎖定之前,使用者在一段時間內允許多少不正確密碼嘗試。預設值為 5。passwordAttemptWindow
- 指出指定數目無效登入嘗試會導致帳戶遭到鎖定的分鐘數。預設值為 10。
如果使用者遭到鎖定,在系統管理員解除鎖定帳戶之前,她無法登入。 當使用者遭到鎖定時,即使提供有效的認證, ValidateUser
方法 一律 會傳回 False
。 雖然此行為可降低駭客透過暴力密碼破解方法進入網站的可能性,但最後可能會鎖定只忘記密碼或意外擁有 CAPS LOCK 或輸入錯誤的日期的有效使用者。
可惜的是,沒有內建工具可用來解除鎖定使用者帳戶。 若要解除鎖定帳戶,您可以直接修改資料庫 - 變更 IsLockedOut
適當使用者帳戶的資料表中的 aspnet_Membership
欄位,或建立 Web 型介面,其中列出鎖定的帳戶與選項來解除鎖定。 我們將在未來的教學課程中檢查如何建立系統管理介面,以完成常見的使用者帳戶和角色相關工作。
注意
方法的 ValidateUser
其中一個缺點是,當提供的認證無效時,它不會提供原因的任何說明。 認證可能無效,因為使用者存放區中沒有相符的使用者名稱/密碼組,或使用者尚未核准,或因為使用者已被鎖定。在步驟 4 中,我們將瞭解如何在使用者登入嘗試失敗時向使用者顯示更詳細的訊息。
步驟 2:透過登入 Web 控制項收集認證
登入 Web 控制項轉譯的預設使用者介面與我們在表單驗證概觀教學課程中 建立的預設使用者介面非常類似。 使用 Login 控制項可節省建立介面以收集訪客認證的工作。 此外,登入控制項會自動登入使用者 (假設提交的認證是有效的) ,藉此讓我們不必撰寫任何程式碼。
讓我們更新 Login.aspx
,並以 Login 控制項取代手動建立的介面和程式碼。 首先,移除 中的現有標記和程式 Login.aspx
代碼。 您可以直接刪除它,或只是將它標記為批註。若要批註化宣告式標記,請使用 和 --%>
分隔符號括住 <%--
它。 您可以手動輸入這些分隔符號,或者,如圖 2 所示,您可以選取要批註化的文字,然後按一下工具列中選取的行圖示批註化。 同樣地,您可以使用 [批註化選取的行] 圖示,將程式碼後置類別中的選取程式碼批註化。
圖 2:批註化 Login.aspx 中的現有宣告式標記和原始程式碼 (按一下即可檢視完整大小的影像)
注意
在 Visual Studio 2005 中檢視宣告式標記時,無法使用 [批註化選取的行] 圖示。 如果您未使用 Visual Studio 2008,則必須手動新增 <%--
和 --%>
分隔符號。
接下來,將 [工具箱] 中的 [登入] 控制項拖曳至頁面,並將其 ID
屬性設定為 myLogin
。 此時,您的畫面看起來應該類似圖 3。 請注意,登入控制項的預設介面包含使用者名稱和密碼的 TextBox 控制項、下一次 CheckBox 記住我,以及 [登入] 按鈕。 另外 RequiredFieldValidator
還有兩個 TextBox 的控制項。
圖 3:將登入控制項新增至頁面 (按一下即可檢視完整大小的影像)
我們已完成! 按一下 [登入] 控制項的 [登入] 按鈕時,就會發生回傳,而登入控制項會呼叫 Membership.ValidateUser
方法,並傳入輸入的使用者名稱和密碼。 如果認證無效,登入控制項會顯示一則訊息,指出這類資訊。 不過,如果認證有效,則登入控制項會建立表單驗證票證,並將使用者重新導向至適當的頁面。
登入控制項會使用四個因素來判斷適當的頁面,以在成功登入時將使用者重新導向至 :
- 登入控制項是否位於登入頁面上,如
loginUrl
表單驗證組態中的設定所定義;此設定的預設值為Login.aspx
- querystring 參數是否存在
ReturnUrl
- Login 控制項的
DestinationUrl
屬性值 defaultUrl
表單驗證組態設定中指定的值;此設定的預設值為 Default.aspx
圖 4 描述登入控制項如何使用這四個參數來到達其適當的頁面決策。
圖 4:將登入控制項新增至頁面 (按一下即可檢視完整大小的影像)
請花點時間測試登入控制項,方法是透過瀏覽器流覽網站,並以成員資格架構中的現有使用者身分登入。
登入控制項的轉譯介面高度可設定。 有數個會影響其外觀的屬性;更重要的是,登入控制項可以轉換成範本,以精確控制使用者介面元素的配置。 此步驟的其餘部分會檢查如何自訂外觀和版面配置。
自訂登入控制項的外觀
登入控制項的預設屬性設定會轉譯使用者介面,其中包含標題 (登入) 、TextBox 和 Label 控制項的使用者名稱和密碼輸入、下次 CheckBox 和 [登入] 按鈕。 這些元素的外觀全都可以透過 Login 控制項的許多屬性來設定。 此外,其他使用者介面元素,例如建立新使用者帳戶的頁面連結,可以藉由設定 屬性或兩個來新增。
讓我們花一些時間來擷取登入控制項的外觀。 Login.aspx
由於頁面在顯示 Login 的頁面頂端已經有文字,所以登入控制項的標題是多餘的。 因此,清除TitleText
屬性值,以移除 Login 控制項的標題。
您可以分別透過 UserNameLabelText
和 屬性自訂兩個 TextBox 控制項左邊的 [使用者名稱:] 和PasswordLabelText
[密碼:標籤]。 讓我們變更 [使用者名稱:標籤] 來讀取 Username:。 標籤和 TextBox 樣式可分別透過 LabelStyle
和TextBoxStyle
屬性進行設定。
下一次 CheckBox 的 Text 屬性可以透過 Login 控制項的RememberMeText
屬性來設定,而且其預設的核取狀態可透過RememberMeSet
屬性 (設定為 False) 。 繼續並將 RememberMeSet
屬性設定為 True,以便下次核取 CheckBox 時記住我。
登入控制項提供兩個屬性來調整其使用者介面控制項的配置。 屬性 TextLayout
會指出 [使用者名稱:] 和 [密碼:標籤] 是否出現在其對應的 TextBox 左邊, (預設) 或上方。 屬性 Orientation
會指出使用者名稱和密碼輸入是否垂直置於另一個) 上方或水準 (。 我即將將這兩個屬性設定為預設值,但建議您嘗試將這兩個屬性設定為其非預設值,以查看產生的效果。
注意
在下一節中,設定登入控制項的版面配置,我們將探討如何使用範本來定義版面配置控制項使用者介面元素的精確版面配置。
將 和CreateUserUrl
屬性設定 CreateUserText
為 [尚未註冊] 來總結登入控制項的屬性設定? 建立帳戶! 分別和 ~/Membership/CreatingUserAccounts.aspx
。 這會將超連結新增至登入控制項的介面,指向我們在上一個教學課程中 建立的頁面。 登入控制項的 HelpPageText
和HelpPageUrl
屬性和 PasswordRecoveryText
PasswordRecoveryUrl
屬性的運作方式相同,轉譯說明頁面和密碼復原頁面的連結。
進行這些屬性變更之後,登入控制項的宣告式標記和外觀看起來應該類似圖 5 所示。
圖 5:登入控制項的屬性值指定其外觀, (按一下即可檢視完整大小的影像)
設定登入控制項的配置
登入 Web 控制項的預設使用者介面會在 HTML <table>
中配置 介面。 但如果我們需要更精細地控制轉譯的輸出,該怎麼辦? 或許我們想要以一系列標記 <div>
取代 <table>
。 或者,如果我們的應用程式需要額外的認證進行驗證,該怎麼辦? 例如,許多財務網站要求使用者不僅提供使用者名稱和密碼,也要求使用者提供個人識別碼 (PIN) 或其他識別資訊。 無論原因為何,都可以將 Login 控制項轉換成範本,我們可以從中明確定義介面的宣告式標記。
我們需要執行兩件事,才能更新登入控制項以收集其他認證:
- 更新登入控制項的 介面,以包含 Web 控制項 () 以收集其他認證。
- 覆寫登入控制項的內部驗證邏輯,如此一來,只有當使用者的使用者名稱和密碼有效且其其他認證有效時,才會驗證使用者。
若要完成第一項工作,我們需要將 Login 控制項轉換成範本,並新增必要的 Web 控制項。 如同第二項工作,登入控制項的驗證邏輯可以藉由建立控制項Authenticate
事件的事件處理常式來取代。
讓我們更新登入控制項,使其提示使用者輸入其使用者名稱、密碼和電子郵件地址,而且只有在提供的電子郵件地址符合檔案上的電子郵件地址時,才會驗證使用者。 我們必須先將登入控制項的介面轉換成範本。 從 [登入] 控制項的 [智慧標籤] 中,選擇 [轉換成範本] 選項。
圖 6:將登入控制項轉換成範本 (按一下即可檢視完整大小的映射)
注意
若要將登入控制項還原為其範本前版本,請按一下控制項智慧標籤中的 [重設] 連結。
將登入控制項轉換成範本,會將 加入 LayoutTemplate
至控制項的宣告式標記,其中 HTML 元素和定義使用者介面的 Web 控制項。 如圖 7 所示,將控制項轉換成範本會移除屬性視窗中的一些屬性,例如 TitleText
、 CreateUserUrl
等等,因為這些屬性值在使用範本時會被忽略。
圖 7:當登入控制項轉換成範本時,可以使用較少的屬性 (按一下即可檢視完整大小的映射)
中的 LayoutTemplate
HTML 標籤可能會視需要修改。 同樣地,您可以隨意將任何新的 Web 控制項新增至範本。 不過,登入控制項的核心 Web 控制項必須保留在範本中,並保留其指派 ID
的值。 特別是,請勿移除或重新命名 UserName
或 Password
TextBox、 RememberMe
CheckBox、 LoginButton
Button、 FailureText
Label 或 RequiredFieldValidator
控制項。
若要收集訪客的電子郵件地址,我們需要將 TextBox 新增至範本。 在資料表資料列 () <tr>
之間新增下列宣告式標記,其中包含 Password
TextBox,以及下次 CheckBox 保留 [記住我] 的資料表資料列:
<tr>
<td align="right">
<asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">Email:</asp:Label>
</td>
<td>
<asp:TextBox ID="Email" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="EmailRequired" runat="server"
ControlToValidate="Email" ErrorMessage="Email is required."
ToolTip="Email is required." ValidationGroup="myLogin">*</asp:RequiredFieldValidator>
</td>
</tr>
新增 Email
TextBox 之後,請透過瀏覽器流覽頁面。 如圖 8 所示,登入控制項的使用者介面現在包含第三個文字方塊。
圖 8:登入控制項現在包含使用者Email位址的文字方塊, (按一下即可檢視完整大小的影像)
此時,登入控制項仍在使用 Membership.ValidateUser
方法來驗證提供的認證。 相對地,輸入 Email
至 TextBox 的值與使用者是否可以登入沒有任何關係。 在步驟 3 中,我們將探討如何覆寫登入控制項的驗證邏輯,如此一來,只有在使用者名稱和密碼有效且提供的電子郵件地址與檔案上的電子郵件地址相符時,才會將認證視為有效。
步驟 3:修改登入控制項的驗證邏輯
當訪客提供其認證並按一下 [登入] 按鈕時,回傳會進行,而登入控制項會透過其驗證工作流程進行。 工作流程一開始會引發LoggingIn
事件。 與這個事件相關聯的任何事件處理常式,都可能會藉由將 e.Cancel
屬性設定為 True
來取消登入作業。
如果未取消登入作業,工作流程會藉由引發Authenticate
事件進行。 如果事件有事件處理常式 Authenticate
,則負責判斷提供的認證是否有效。 如果未指定事件處理常式,Login 控制項會 Membership.ValidateUser
使用 方法來判斷認證的有效性。
如果提供的認證有效,則會建立表單驗證票證、LoggedIn
引發事件,並將使用者重新導向至適當的頁面。 不過,如果認證被視為無效,則會LoginError
引發事件,並顯示訊息,告知使用者其認證無效。 根據預設,登入控制項在失敗時,只會將其 FailureText
Label 控制項的 Text 屬性設定為失敗訊息, (您的登入嘗試未成功。請再試一次) 。 不過,如果 Login 控制項的FailureAction
屬性設定 RedirectToLoginPage
為 ,則 Login 控制項會對登入頁面發出 Response.Redirect
,並將 附加 querystring 參數 loginfailure=1
(,這會導致 Login 控制項顯示失敗訊息) 。
圖 9 提供驗證工作流程的流程圖。
圖 9:登入控制項的驗證工作流程 (按一下以檢視完整大小的映射)
注意
如果您想知道何時要使用 FailureAction
頁面 RedirectToLogin
選項,請考慮下列案例。 現在,我們的 Site.master
主版頁面目前有匿名使用者流覽時,左側資料行中顯示的文字 Hello,但假設我們想要將該文字取代為 Login 控制項。 這可讓匿名使用者從網站上的任何頁面登入,而不需要他們直接流覽登入頁面。 不過,如果使用者無法透過主版頁面轉譯的登入控制項登入,將他們重新導向至登入頁面 (Login.aspx
) ,因為該頁面可能會包含其他指示、連結和其他說明,例如建立新帳戶的連結或擷取遺失的密碼, 未新增至主版頁面。
Authenticate
建立事件處理常式
為了插入自訂驗證邏輯,我們需要建立 Login 控制項事件的 Authenticate
事件處理常式。 建立事件的事件處理常式 Authenticate
將會產生下列事件處理常式定義:
Protected Sub myLogin_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles myLogin.Authenticate
End Sub
如您所見, Authenticate
事件處理常式會傳遞 類型 AuthenticateEventArgs
的物件做為其第二個輸入參數。 類別 AuthenticateEventArgs
包含名為 Authenticated
的 Boolean 屬性,可用來指定提供的認證是否有效。 接著,我們的工作是在這裡撰寫程式碼,以判斷提供的認證是否有效,並據以設定 e.Authenticate
屬性。
判斷及驗證提供的認證
使用登入控制項的 UserName
和Password
屬性來判斷使用者輸入的使用者名稱和密碼認證。 若要判斷輸入至任何其他 Web 控制項的值, (例如 Email
我們在上一個步驟中新增的 TextBox) ,請使用 LoginControlID.FindControl
(「 controlID
) ,以程式設計方式參考範本中的 Web 控制項,其 ID
屬性等於 controlID
。 例如,若要取得 TextBox 的 Email
參考,請使用下列程式碼:
Dim EmailTextBox As TextBox = CType(myLogin.FindControl("Email"), TextBox)
為了驗證使用者的認證,我們需要執行兩件事:
- 確定所提供的使用者名稱和密碼有效
- 確定輸入的電子郵件地址符合使用者嘗試登入的檔案電子郵件地址
為了完成第一次檢查,我們只要使用 Membership.ValidateUser
步驟 1 中所見的方法即可。 針對第二次檢查,我們需要判斷使用者的電子郵件地址,以便將其與他們輸入至 TextBox 控制項的電子郵件地址進行比較。 若要取得特定使用者的相關資訊,請使用 Membership
類別GetUser
的 方法。
方法 GetUser
有一些多載。 如果使用而不傳入任何參數,則會傳回目前登入使用者的相關資訊。 若要取得特定使用者的相關資訊,請呼叫 GetUser
傳入其使用者名稱。 不論是哪一種方式, GetUser
都傳回物件 MembershipUser
,其屬性如下 UserName
:、 Email
、 IsApproved
、 IsOnline
等等。
下列程式碼會實作這兩個檢查。 如果同時傳遞,則會 e.Authenticate
設定為 True
,否則會指派 False
。
Protected Sub myLogin_Authenticate(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.AuthenticateEventArgs) Handles myLogin.Authenticate
' Get the email address entered
Dim EmailTextBox As TextBox = CType(myLogin.FindControl("Email"), TextBox)
Dim email As String = EmailTextBox.Text.Trim()
' Verify that the username/password pair is valid
If Membership.ValidateUser(myLogin.UserName, myLogin.Password) Then
' Username/password are valid, check email
Dim usrInfo As MembershipUser = Membership.GetUser(myLogin.UserName)
If usrInfo IsNot Nothing AndAlso String.Compare(usrInfo.Email, email, True) = 0 Then
' Email matches, the credentials are valid
e.Authenticated = True
Else
' Email address is invalid...
e.Authenticated = False
End If
Else
' Username/password are not valid...
e.Authenticated = False
End If
End Sub
在此程式碼就緒後,嘗試以有效的使用者身分登入,輸入正確的使用者名稱、密碼和電子郵件地址。 請再試一次,但這次有目的地使用不正確的電子郵件地址, (請參閱圖 10) 。 最後,使用不存在的使用者名稱來嘗試第三次。 在第一種情況下,您應該成功登入網站,但在最後兩種情況下,您應該會看到登入控制項的無效認證訊息。
圖 10:在提供不正確的Email位址時,Tito 無法登入 (按一下即可檢視大小完整的影像)
注意
如步驟 1 中成員資格架構如何處理不正確登入嘗試一節所述,當呼叫 方法並傳遞不正確認證時 Membership.ValidateUser
,它會追蹤不正確登入嘗試,並在超過指定時間範圍內無效嘗試的特定臨界值時鎖定使用者。 由於我們的自訂驗證邏輯會呼叫 ValidateUser
方法,有效使用者名稱的密碼會遞增不正確登入嘗試計數器,但在使用者名稱和密碼有效的情況下,此計數器不會遞增,但電子郵件地址不正確。 這種行為很適合,因為駭客不太可能知道使用者名稱和密碼,但必須使用暴力密碼破解技術來判斷使用者的電子郵件地址。
步驟 4:改善登入控制項的無效認證訊息
當使用者嘗試以不正確認證登入時,登入控制項會顯示一則訊息,說明登入嘗試失敗。 特別是,控制項會顯示其FailureText
屬性所指定的訊息,其預設值為 [您的登入嘗試] 未成功。 請再試一次。
回想一下,使用者認證可能不正確原因有很多:
- 使用者名稱可能不存在
- 使用者名稱存在,但密碼無效
- 使用者名稱和密碼有效,但使用者尚未核准
- 使用者名稱和密碼有效,但使用者最可能鎖定 (,因為它們超過指定時間範圍內不正確登入嘗試次數)
使用自訂驗證邏輯時,可能會有其他原因。 例如,使用我們在步驟 3 中撰寫的程式碼,使用者名稱和密碼可能有效,但電子郵件地址可能不正確。
不論認證不正確原因為何,登入控制項都會顯示相同的錯誤訊息。 對於尚未核准帳戶或已鎖定的使用者,這種缺乏意見反應可能會造成混淆。不過,雖然有一些工作,但我們可以讓 Login 控制項顯示更適當的訊息。
每當使用者嘗試以不正確認證登入時,Login 控制項就會引發其 LoginError
事件。 繼續並建立此事件的事件處理常式,並新增下列程式碼:
Protected Sub myLogin_LoginError(ByVal sender As Object, ByVal e As System.EventArgs) Handles myLogin.LoginError
' Determine why the user could not login...
myLogin.FailureText = "Your login attempt was not successful. Please try again."
' Does there exist a User account for this user?
Dim usrInfo As MembershipUser = Membership.GetUser(myLogin.UserName)
If usrInfo IsNot Nothing Then
' Is this user locked out?
If usrInfo.IsLockedOut Then
myLogin.FailureText = "Your account has been locked out because of too many invalid login attempts. Please contact the administrator to have your account unlocked."
ElseIf Not usrInfo.IsApproved Then
myLogin.FailureText = "Your account has not yet been approved. You cannot login until an administrator has approved your account."
End If
End If
End Sub
上述程式碼會先將登入控制項的 FailureText
屬性設定為預設值, (您的登入嘗試未成功。請) 再試一次。 然後,它會檢查提供的使用者名稱是否對應至現有的使用者帳戶。 如果是,則會參考產生的 MembershipUser
物件 IsLockedOut
和 IsApproved
屬性,以判斷帳戶是否已鎖定或尚未核准。 不論是哪一種情況, FailureText
屬性都會更新為對應的值。
若要測試此程式碼,請以現有的使用者身分嘗試登入,但使用不正確的密碼。 在 10 分鐘的時間範圍內,在一個資料列中執行這五次,且帳戶將會遭到鎖定。如圖 11 所示,即使有正確的密碼) ,後續登入嘗試一律會失敗 (,但現在會顯示更具描述性的您的帳戶因為登入嘗試太多而遭到鎖定。 請連絡系統管理員,讓您的帳戶解除鎖定訊息。
圖 11:Tito 執行太多不正確登入嘗試,且已鎖定 (按一下即可檢視大小完整的映射)
摘要
在本教學課程之前,我們的登入頁面會根據使用者名稱/密碼組的硬式編碼清單來驗證提供的認證。 在本教學課程中,我們已更新頁面,以驗證成員資格架構的認證。 在步驟 1 中,我們以程式設計方式探討如何使用 Membership.ValidateUser
方法。 在步驟 2 中,我們已使用登入控制項取代手動建立的使用者介面和程式碼。
登入控制項會轉譯標準登入使用者介面,並針對成員資格架構自動驗證使用者的認證。 此外,在有效認證的情況下,登入控制項會透過表單驗證將使用者登入。 簡單來說,只要將登入控制項拖曳到頁面即可取得功能完整的登入使用者體驗,不需要額外的宣告式標記或程式碼。 進一步來說,登入控制項是高度自訂的,允許對轉譯的使用者介面和驗證邏輯進行精細的控制。
此時,網站的訪客可以建立新的使用者帳戶並登入網站,但我們尚未查看根據已驗證的使用者限制頁面的存取權。 目前,任何經過驗證或匿名的使用者都可以檢視網站上的任何頁面。 除了根據使用者控制網站頁面的存取權之外,我們可能會有特定頁面,其功能取決於使用者。 下一個教學課程會探討如何根據登入的使用者限制存取和頁面內功能。
快樂的程式設計!
深入閱讀
如需本教學課程中討論之主題的詳細資訊,請參閱下列資源:
關於作者
Scott Mitchell 是多個 ASP/ASP.NET 書籍的作者,且 4GuysFromRolla.com 的作者,自 1998 年以來,已與 Microsoft Web 技術合作。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以在 或 透過在 的 http://ScottOnWriting.NET 部落格連線 mitchell@4guysfromrolla.com 到 Scott。
特別感謝
本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Teresa Murphy 和 Michael Olivero。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com 放在 。