解除鎖定及核准使用者帳戶 (C#)
注意
自本文撰寫以來,ASP.NET 成員資格提供者已被 ASP.NET 身分識別取代。 強烈建議您更新應用程式以使用 ASP.NET 身分識別 平臺,而不是本文撰寫時精選的成員資格提供者。 ASP.NET 身分識別對於 ASP.NET 成員資格系統有一些優點,包括 :
- 更好的效能
- 改善擴充性和可測試性
- 支援 OAuth、OpenID Connect 和雙因素驗證
- 宣告型身分識別支援
- 與 ASP.Net Core 更好的互通性
本教學課程說明如何建置網頁,讓系統管理員管理使用者的鎖定和核准狀態。 我們也會瞭解如何在驗證其電子郵件地址之後核准新使用者。
簡介
除了使用者名稱、密碼和電子郵件之外,每個使用者帳戶都有兩個狀態欄位,指出使用者是否可以登入網站:已鎖定和核准。 如果使用者在指定的分鐘數內提供不正確認證,就會自動鎖定使用者, (預設設定會在 10 分鐘內 5 次不正確登入嘗試後鎖定使用者) 。 核准的狀態適用于某些動作必須轉譯,才能讓新使用者登入網站的情況。 例如,使用者可能需要先驗證其電子郵件地址,或由系統管理員核准,才能登入。
因為鎖定或未核准的使用者無法登入,所以只有想知道這些狀態如何重設是自然的。 ASP.NET 不包含用於管理使用者鎖定和核准狀態的任何內建功能或 Web 控制項,部分原因是這些決策必須依網站處理。 某些網站可能會自動核准所有新的使用者帳戶, (預設行為) 。 其他人擁有系統管理員核准新帳戶,或等到他們註冊時傳送至電子郵件地址的連結之後,才核准使用者。 同樣地,某些網站可能會鎖定使用者,直到系統管理員重設其狀態,而其他網站則會使用可造訪的 URL 將電子郵件傳送給鎖定的使用者,以解除鎖定其帳戶。
本教學課程說明如何建置網頁,讓系統管理員管理使用者的鎖定和核准狀態。 我們也會瞭解如何在驗證其電子郵件地址之後核准新使用者。
步驟 1:管理使用者的鎖定和核准狀態
在 [ 建置介面以從許多教學課程中選取一個使用者帳戶] 教學課程中,我們建構了一個頁面,其中列出分頁、篩選的 GridView 中的每個使用者帳戶。 方格會列出每個使用者的名稱和電子郵件、其核准和鎖定的狀態、他們目前是否在線上,以及使用者的任何批註。 若要管理使用者的核准和鎖定狀態,我們可以讓此方格可編輯。 若要變更使用者的核准狀態,系統管理員會先找出使用者帳戶,然後編輯對應的 GridView 資料列,並核取或取消核取核准的核取方塊。 或者,我們可以透過個別 ASP.NET 網頁來管理已核准和鎖定的狀態。
在本教學課程中,我們將使用兩個 ASP.NET 網頁: ManageUsers.aspx
和 UserInformation.aspx
。 這裡的概念是列出 ManageUsers.aspx
系統中的使用者帳戶,而 UserInformation.aspx
可讓系統管理員管理特定使用者的核准和鎖定狀態。 我們的第一個業務順序是將 GridView 擴增至 , ManageUsers.aspx
以包含 HyperLinkField,它會轉譯為連結的資料行。 我們希望每個連結指向 UserInformation.aspx?user=UserName
,其中 UserName 是要編輯的使用者名稱。
注意
如果您已下載復原和變更密碼教學課程的程式碼 ,您可能已注意到 ManageUsers.aspx
頁面已經包含一組「管理」連結,而 UserInformation.aspx
頁面會提供用來變更所選使用者密碼的介面。 我決定不要在與本教學課程相關聯的程式碼中複寫該功能,因為它的運作方式是規避成員資格 API,並直接使用 SQL Server 資料庫操作,以變更使用者的密碼。 本教學課程從頭開始與 UserInformation.aspx
頁面。
將 「管理」連結新增至 UserAccounts
GridView
開啟頁面, ManageUsers.aspx
並將 HyperLinkField 新增至 UserAccounts
GridView。 分別將 HyperLinkField 的 Text
屬性設定為 「Manage」,並將其 DataNavigateUrlFields
和 DataNavigateUrlFormatString
屬性分別設定為 UserName
和 「UserInformation.aspx?user= {0} 」。 這些設定會設定 HyperLinkField,讓所有超連結都顯示文字 「Manage」,但每個連結都會傳入適當的 UserName 值至 querystring。
將 HyperLinkField 新增至 GridView 之後,請花點時間透過瀏覽器檢視 ManageUsers.aspx
頁面。 如圖 1 所示,每個 GridView 資料列現在都包含「管理」連結。 Bruce 的 [管理] 連結指向 UserInformation.aspx?user=Bruce
,而 Dave 的 [管理] 連結則指向 UserInformation.aspx?user=Dave
。
圖 1:HyperLinkField 新增每個使用者帳戶的「管理」連結 (按一下即可檢視完整大小的映射)
我們會在一段時間建立頁面的使用者介面和程式碼 UserInformation.aspx
,但首先讓我們來討論如何以程式設計方式變更使用者的鎖定和核准狀態。 類別MembershipUser
具有IsLockedOut
和IsApproved
屬性。 IsLockedOut
屬性是唯讀的。 沒有以程式設計方式鎖定使用者的機制;若要解除鎖定使用者,請使用 MembershipUser
類別的UnlockUser
方法。 屬性 IsApproved
是可讀取且可寫入的。 若要儲存此屬性的任何變更,我們需要呼叫 Membership
類別的UpdateUser
方法,並傳入修改 MembershipUser
的物件。
IsApproved
因為屬性是可讀取且可寫入的,所以 CheckBox 控制項可能是設定此屬性的最佳使用者介面元素。 不過,CheckBox 無法用於 IsLockedOut
屬性,因為系統管理員無法鎖定使用者,她只能解除鎖定使用者。 屬性的適當使用者介面 IsLockedOut
是按鈕,按一下時會解除鎖定使用者帳戶。 只有當使用者遭到鎖定時,才應該啟用此按鈕。
UserInformation.aspx
建立頁面
我們現在已準備好在 中 UserInformation.aspx
實作使用者介面。 開啟此頁面並新增下列 Web 控制項:
- 當按一下時,HyperLink 控制項會將系統管理員傳
ManageUsers.aspx
回頁面。 - 用於顯示所選使用者名稱的標籤 Web 控制項。 將此標籤設定為
ID
UserNameLabel
,並清除其Text
屬性。 - 名為 的
IsApproved
CheckBox 控制項。 將其AutoPostBack
屬性設定為true
。 - 用於顯示使用者上次鎖定日期的標籤控制項。 將此標籤
LastLockedOutDateLabel
命名為 ,並清除其Text
屬性。 - 用於解除鎖定使用者的按鈕。 將此按鈕
UnlockUserButton
命名為 ,並將其Text
屬性設定為 [解除鎖定使用者]。 - 顯示狀態訊息的標籤控制項,例如「使用者的核准狀態已更新」。將此控制項
StatusMessage
命名為 、清除其Text
屬性,並將其 屬性設定CssClass
為Important
。 (Important
CSS 類別是在樣式表單檔案中Styles.css
定義;它會以大型紅色字型顯示對應文字。)
新增這些控制項之後,Visual Studio 中的 [設計] 檢視看起來應該類似圖 2 中的螢幕擷取畫面。
圖 2:建立 (使用者介面 UserInformation.aspx
按一下即可檢視完整大小的影像)
完成使用者介面之後,下一項工作是根據選取的使用者資訊來設定 IsApproved
CheckBox 和其他控制項。 建立頁面 Load
事件的事件處理常式,並新增下列程式碼:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// If querystring value is missing, send the user to ManageUsers.aspx
string userName = Request.QueryString["user"];
if (string.IsNullOrEmpty(userName))
Response.Redirect("ManageUsers.aspx");
// Get information about this user
MembershipUser usr = Membership.GetUser(userName);
if (usr == null)
Response.Redirect("ManageUsers.aspx");
UserNameLabel.Text = usr.UserName;
IsApproved.Checked = usr.IsApproved;
if (usr.LastLockoutDate.Year < 2000)
LastLockoutDateLabel.Text = string.Empty;
else
LastLockoutDateLabel.Text = usr.LastLockoutDate.ToShortDateString();
UnlockUserButton.Enabled = usr.IsLockedOut;
}
}
上述程式碼一開始會確保這是第一次流覽頁面,而不是後續回傳。 然後它會讀取透過 user
querystring 欄位傳遞的使用者名稱,並透過 Membership.GetUser(username)
方法擷取該使用者帳戶的相關資訊。 如果未透過 querystring 提供使用者名稱,或找不到指定的使用者,系統就會將系統管理員傳回 ManageUsers.aspx
頁面。
然後,物件的 MembershipUser
UserName
值會顯示在 中 UserNameLabel
, IsApproved
並且會根據 IsApproved
屬性值檢查 CheckBox。
物件的 MembershipUser
屬性會LastLockoutDate
傳回值 DateTime
,指出使用者上次鎖定的時間。如果使用者從未遭到鎖定,傳回的值取決於成員資格提供者。 建立新帳戶時,會將 SqlMembershipProvider
資料表的 LastLockoutDate
欄位設定 aspnet_Membership
為 1754-01-01 12:00:00 AM
。 如果屬性發生在 2000 年之前,上述程式碼會在 中 LastLockoutDateLabel
LastLockoutDate
顯示空字串;否則,屬性的 LastLockoutDate
日期部分會顯示在 Label 中。 屬性 UnlockUserButton'
Enabled
會設定為使用者的鎖定狀態,這表示只有在使用者遭到鎖定時,才會啟用此 Button。
請花點時間透過瀏覽器測試 UserInformation.aspx
頁面。 當然,您必須從 開始 ManageUsers.aspx
,並選取要管理的使用者帳戶。 到達 UserInformation.aspx
時,請注意 IsApproved
,只有在使用者獲得核准時,才會檢查 CheckBox。 如果使用者曾遭到鎖定,則會顯示其上次鎖定的日期。 只有在使用者目前已鎖定時,才會啟用 [解除鎖定使用者] 按鈕。核取 IsApproved
或取消核取 CheckBox 或按一下 [解除鎖定使用者] 按鈕會導致回傳,但不會修改使用者帳戶,因為我們尚未為這些事件建立事件處理常式。
返回 Visual Studio 並建立 CheckBox CheckedChanged
事件和 UnlockUser
Button Click
事件的事件處理常式 IsApproved
。 在 CheckedChanged
事件處理常式中,將使用者的 IsApproved
屬性設定為 Checked
CheckBox 的 屬性,然後透過呼叫 Membership.UpdateUser
儲存變更。 在事件處理常式中 Click
,只要呼叫 MembershipUser
物件的 UnlockUser
方法即可。 在這兩個事件處理常式中,在標籤中 StatusMessage
顯示適當的訊息。
protected void IsApproved_CheckedChanged(object sender, EventArgs e)
{
// Toggle the user's approved status
string userName = Request.QueryString["user"];
MembershipUser usr = Membership.GetUser(userName);
usr.IsApproved = IsApproved.Checked;
Membership.UpdateUser(usr);
StatusMessage.Text = "The user's approved status has been updated.";
}
protected void UnlockUserButton_Click(object sender, EventArgs e)
{
// Unlock the user account
string userName = Request.QueryString["user"];
MembershipUser usr = Membership.GetUser(userName);
usr.UnlockUser();
UnlockUserButton.Enabled = false;
StatusMessage.Text = "The user account has been unlocked.";
}
UserInformation.aspx
測試頁面
有了這些事件處理常式,請重新流覽頁面並取消核准使用者。 如圖 3 所示,您應該會在頁面上看到簡短訊息,指出使用者 IsApproved
的屬性已成功修改。
圖 3:Chris 已取消核准 (按一下即可檢視完整大小的影像)
接下來,登出並嘗試以剛未核准帳戶的使用者身分登入。 因為使用者未經核准,所以無法登入。 根據預設,不論原因為何,登入控制項都會在使用者無法登入時顯示相同的訊息。 但在針對成員資格使用者存放區驗證使用者認證教學課程中 ,我們探討如何增強登入控制項以顯示更適當的訊息。 如圖 4 所示,Chris 會顯示一則訊息,說明他因為尚未核准帳戶而無法登入。
圖 4:Chris 無法登入,因為其帳戶未經核准 (按一下即可檢視完整大小的影像)
若要測試鎖定的功能,請嘗試以核准的使用者身分登入,但使用不正確的密碼。 重複此程式的必要次數,直到使用者帳戶遭到鎖定為止。如果嘗試從鎖定的帳戶登入,登入控制項也會更新為顯示自訂訊息。 當您開始在登入頁面上看到下列訊息時,您知道帳戶已遭到鎖定:「您的帳戶因為太多不正確登入嘗試而遭到鎖定。 請連絡系統管理員,讓您的帳戶解除鎖定。」
ManageUsers.aspx
返回頁面,然後按一下鎖定使用者的 [管理] 連結。 如圖 5 所示,您應該會在 [解除鎖定使用者] 按鈕中看到 LastLockedOutDateLabel
應啟用的值。 按一下 [解除鎖定使用者] 按鈕來解除鎖定使用者帳戶。 一旦您解除鎖定使用者,他們就能夠再次登入。
圖 5:Dave 已鎖定系統 (按一下即可檢視完整大小的映射)
步驟 2:指定新使用者的核准狀態
在您希望在新使用者能夠登入及存取網站使用者特定功能的案例中,核准的狀態很有用。 例如,您可能會執行私人網站,其中除了登入和註冊頁面以外,所有頁面都只能供已驗證的使用者存取。 但是,如果某個訊息到達您的網站、尋找註冊頁面並建立帳戶,會發生什麼事? 若要避免發生這種情況,您可以將註冊頁面 Administration
移至資料夾,並要求系統管理員手動建立每個帳戶。 或者,您可以允許任何人註冊,但禁止網站存取,直到系統管理員核准使用者帳戶為止。
根據預設,CreateUserWizard 控制項會核准新的帳戶。 您可以使用 控制項的DisableCreatedUser
屬性來設定此行為。 將此屬性設定為 true
,以不核准新的使用者帳戶。
注意
根據預設,CreateUserWizard 控制項會自動登入新的使用者帳戶。 此行為是由 控制項的LoginCreatedUser
屬性所決定。 因為未經核准的使用者無法登入網站, DisableCreatedUser
所以當 新 true
使用者帳戶未登入網站時,不論 屬性的值 LoginCreatedUser
為何。
如果您是透過 Membership.CreateUser
方法以程式設計方式建立新的使用者帳戶,若要建立未核准的使用者帳戶,請使用接受新使用者屬性值作為輸入參數的 IsApproved
其中一個多載。
步驟 3:驗證使用者的Email位址來核准使用者
許多支援使用者帳戶的網站在驗證註冊時提供的電子郵件地址之前,都不會核准新的使用者。 此驗證程式通常用來阻止 Bot、垃圾郵件者和其他 ne'er-do-wells,因為它需要唯一、已驗證的電子郵件地址,並在註冊程式中新增額外的步驟。 使用此模型時,當新使用者註冊時,系統會傳送包含驗證頁面連結的電子郵件訊息。 藉由造訪連結,使用者已證明他們收到電子郵件,因此提供的電子郵件地址有效。 驗證頁面負責核准使用者。 這可能會自動發生,因此核准任何到達此頁面的使用者,或只在使用者提供一些額外的資訊之後,例如 CAPTCHA。
為了容納此工作流程,我們必須先更新帳戶建立頁面,讓新使用者未經核准。 EnhancedCreateUserWizard.aspx
開啟 資料夾中的頁面 Membership
,並將 CreateUserWizard 控制項的 DisableCreatedUser
屬性設定為 true
。
接下來,我們需要設定 CreateUserWizard 控制項,以傳送電子郵件給新使用者,並說明如何驗證其帳戶。 特別是,我們會在電子郵件 Verification.aspx
中包含頁面的連結, (尚未建立) ,並透過 querystring 傳入新使用者的 UserId
。 頁面 Verification.aspx
會查閱指定的使用者,並標示其已核准。
將驗證Email傳送給新使用者
若要從 CreateUserWizard 控制項傳送電子郵件,請適當地設定其 MailDefinition
屬性。 如上一個MailDefinition
教學課程所述 ,ChangePassword 和 PasswordRecovery 控制項包含與 CreateUserWizard 控制項相同方式運作的屬性。
注意
若要使用 屬性, MailDefinition
您必須在 中 Web.config
指定郵件傳遞選項。 如需詳細資訊,請參閱在 ASP.NET 中傳送Email。
首先,在 資料夾中建立名為 CreateUserWizard.txt
EmailTemplates
的新電子郵件範本。 針對範本使用下列文字:
Hello <%UserName%>! Welcome aboard.
Your new account is almost ready, but before you can login you must first visit:
<%VerificationUrl%>
Once you have visited the verification URL you will be redirected to the login page.
If you have any problems or questions, please reply to this email.
Thanks!
將 MailDefinition'
s BodyFileName
屬性設定為 「~/EmailTemplates/CreateUserWizard.txt」,並將其 Subject
屬性設定為 「Welcome to My Website! 請啟用您的帳戶。」
請注意, CreateUserWizard.txt
電子郵件範本包含 <%VerificationUrl%>
預留位置。 這是將放置頁面 URL Verification.aspx
的位置。 CreateUserWizard 會自動以新帳戶的使用者名稱和密碼取代 <%UserName%>
和 <%Password%>
預留位置,但沒有內 <%VerificationUrl%>
建預留位置。 我們需要手動將它取代為適當的驗證 URL。
若要達成此目的,請建立 CreateUserWizard SendingMail
事件的事件處理常式,並新增下列程式碼:
protected void NewUserWizard_SendingMail(object sender, MailMessageEventArgs e)
{
// Get the UserId of the just-added user
MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
Guid newUserId = (Guid)newUser.ProviderUserKey;
// Determine the full verification URL (i.e., http://yoursite.com/Verification.aspx?ID=...)
string urlBase = Request.Url.GetLeftPart(UriPartial.Authority) +
Request.ApplicationPath;
string verifyUrl = "/Verification.aspx?ID=" + newUserId.ToString();
string fullUrl = urlBase + verifyUrl;
// Replace <%VerificationUrl%> with the appropriate URL and querystring
e.Message.Body = e.Message.Body.Replace("<%VerificationUrl%>", fullUrl);
}
事件 SendingMail
會在 事件之後 CreatedUser
引發,這表示在上述事件處理常式執行新的使用者帳戶已經建立時。 我們可以藉由呼叫 Membership.GetUser
方法來存取新使用者 UserId
的值, UserName
傳入輸入的 CreateUserWizard 控制項。 接下來,驗證 URL 會形成。 語句 Request.Url.GetLeftPart(UriPartial.Authority)
會傳 http://yourserver.com
回 URL 的部分; Request.ApplicationPath
傳回應用程式根目錄的路徑。 驗證 URL 接著會 Verification.aspx?ID=userId
定義為 。 接著會串連這兩個字串,以形成完整的 URL。 最後,電子郵件訊息本文 (e.Message.Body
) 已全部取代 <%VerificationUrl%>
為完整 URL。
淨效果是新使用者未經核准,這表示他們無法登入網站。 此外,他們會自動傳送含有驗證 URL 連結的電子郵件, (請參閱圖 6) 。
圖 6:新使用者收到具有 [驗證 URL 連結] 的Email, (按一下即可檢視完整大小的影像)
注意
CreateUserWizard 控制項的預設 CreateUserWizard 步驟會顯示一則訊息,告知其帳戶已建立並顯示 [繼續] 按鈕。 按一下此選項會將使用者帶到控制項的 ContinueDestinationPageUrl
屬性所指定的 URL。 中的 EnhancedCreateUserWizard.aspx
CreateUserWizard 設定為將新使用者傳送至 ~/Membership/AdditionalUserInfo.aspx
,提示使用者輸入其首頁、首頁 URL 和簽章。 由於這項資訊只能由登入的使用者新增,因此更新此屬性可將使用者傳回網站的首頁 (~/Default.aspx
) 。 此外, EnhancedCreateUserWizard.aspx
應該增強頁面或 CreateUserWizard 步驟,以通知使用者他們已傳送驗證電子郵件,而且除非他們遵循此電子郵件中的指示,否則不會啟用其帳戶。 我將這些修改保留為讀者的練習。
建立驗證頁面
最後一項工作是建立 Verification.aspx
頁面。 將此頁面新增至根資料夾,並將它與 Site.master
主版頁面產生關聯。 如同我們已將大部分先前的內容頁面新增至網站一樣,請移除參考 LoginContent
ContentPlaceHolder 的內容控制項,讓內容頁面使用主版頁面的預設內容。
將標籤 Web 控制項新增至 Verification.aspx
頁面、將其設定為 StatusMessage
ID
,並清除其文字屬性。 接下來,建立 Page_Load
事件處理常式並新增下列程式碼:
protected void Page_Load(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(Request.QueryString["ID"]))
StatusMessage.Text = "The UserId was not included in the querystring...";
else
{
Guid userId;
try
{
userId = new Guid(Request.QueryString["ID"]);
}
catch
{
StatusMessage.Text = "The UserId passed into the querystring is not in the
proper format...";
return;
}
MembershipUser usr = Membership.GetUser(userId);
if (usr == null)
StatusMessage.Text = "User account could not be found...";
else
{
// Approve the user
usr.IsApproved = true;
Membership.UpdateUser(usr);
StatusMessage.Text = "Your account has been approved.
Please <a href=\"Login.aspx\">login</a> to the site.";
}
}
}
上述程式碼的大部分會 UserId
驗證透過 querystring 提供的 是否存在、它是有效的 Guid
值,以及它參考現有的使用者帳戶。 如果所有這些檢查都通過,則會核准使用者帳戶;否則會顯示適當的狀態訊息。
圖 7 顯示 Verification.aspx
透過瀏覽器流覽的頁面。
圖 7:新使用者帳戶現在已核准, (按一下即可檢視完整大小的映射)
摘要
所有成員資格使用者帳戶都有兩種狀態,可判斷使用者是否可以登入網站: IsLockedOut
和 IsApproved
。 這兩個屬性都必須 true
讓使用者登入。
使用者的鎖定狀態會用來作為安全性措施,以減少駭客透過暴力密碼破解方法入侵網站的可能性。 具體而言,如果使用者在特定時段內有特定數目不正確登入嘗試,就會遭到鎖定。 這些界限可透過 中的 Web.config
成員資格提供者設定來設定。
核准的狀態通常用來禁止新使用者登入,直到發生某些動作為止。 或許網站要求系統管理員先核准新帳戶,或如我們在步驟 3 中所見,驗證其電子郵件地址。
快樂的程式設計!
關於作者
Scott Mitchell 是多個 ASP/ASP.NET 書籍的作者,且 4GuysFromRolla.com 的作者,自 1998 年以來,已與 Microsoft Web 技術合作。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以在 或 透過在 的 http://ScottOnWriting.NET 部落格連線 mitchell@4guysfromrolla.com 到 Scott。
特別感謝...
本教學課程系列是由許多實用的檢閱者檢閱。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在我 mitchell@4GuysFromRolla.com