ASP.NET Core 中的帳戶確認和密碼復原 Blazor
本文說明如何使用電子郵件確認和密碼復原來設定 ASP.NET Core Blazor Web 應用程式。
Namespace
本文範例所使用的應用程式命名空間為 BlazorSample
。 更新程式代碼範例以使用您應用程式的命名空間。
選取並設定電子郵件提供者
在本文中, Mailchimp 的交易式 API 是透過 Mandrill.net 來傳送電子郵件。 我們建議使用電子郵件服務來傳送電子郵件,而不是 SMTP。 SMTP 難以正確設定及保護。 無論您使用哪一個電子郵件服務、存取其 .NET 應用程式的指引、建立帳戶、為其服務設定 API 金鑰,以及安裝所需的任何 NuGet 套件。
建立類別以擷取安全的電子郵件 API 金鑰。 本文中的範例會使用名為 AuthMessageSenderOptions
的 EmailAuthKey
類別搭配 屬性來保存索引鍵。
AuthMessageSenderOptions
:
namespace BlazorSample;
public class AuthMessageSenderOptions
{
public string? EmailAuthKey { get; set; }
}
在 AuthMessageSenderOptions
檔案中 Program
註冊組態實例:
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
為提供者的安全性金鑰設定用戶密碼
使用 秘密管理員工具設定金鑰。 在下列範例中,索引鍵名稱為 EmailAuthKey
,而索引鍵則以 {KEY}
佔位元表示。 在命令殼層中,瀏覽至應用程式的根資料夾,並使用 API 金鑰執行下列命令:
dotnet user-secrets set "EmailAuthKey" "{KEY}"
如需詳細資訊,請參閱 ASP.NET Core 中開發中的應用程式密碼安全儲存。
實作 IEmailSender
IEmailSender
針對提供者實作 。 下列範例是以 Mailchimp 的交易式 API 為基礎,使用 Mandrill.net。 如需不同的提供者,請參閱其檔,以瞭解如何在方法中 Execute
實作傳送訊息。
Components/Account/EmailSender.cs
:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Mandrill;
using Mandrill.Model;
using BlazorSample.Data;
namespace BlazorSample.Components.Account;
public class EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
ILogger<EmailSender> logger) : IEmailSender<ApplicationUser>
{
private readonly ILogger logger = logger;
public AuthMessageSenderOptions Options { get; } = optionsAccessor.Value;
public Task SendConfirmationLinkAsync(ApplicationUser user, string email,
string confirmationLink) => SendEmailAsync(email, "Confirm your email",
$"Please confirm your account by " +
"<a href='{confirmationLink}'>clicking here</a>.");
public Task SendPasswordResetLinkAsync(ApplicationUser user, string email,
string resetLink) => SendEmailAsync(email, "Reset your password",
$"Please reset your password by <a href='{resetLink}'>clicking here</a>.");
public Task SendPasswordResetCodeAsync(ApplicationUser user, string email,
string resetCode) => SendEmailAsync(email, "Reset your password",
$"Please reset your password using the following code: {resetCode}");
public async Task SendEmailAsync(string toEmail, string subject, string message)
{
if (string.IsNullOrEmpty(Options.EmailAuthKey))
{
throw new Exception("Null EmailAuthKey");
}
await Execute(Options.EmailAuthKey, subject, message, toEmail);
}
public async Task Execute(string apiKey, string subject, string message,
string toEmail)
{
var api = new MandrillApi(apiKey);
var mandrillMessage = new MandrillMessage("sarah@contoso.com", toEmail,
subject, message);
await api.Messages.SendAsync(mandrillMessage);
logger.LogInformation("Email to {EmailAddress} sent!", toEmail);
}
}
注意
郵件的本文內容可能需要電子郵件服務提供者的特殊編碼方式。 如果無法遵循訊息本文中的連結,請參閱服務提供者的檔。
設定應用程式以支援電子郵件
在檔案中 Program
,將電子郵件寄件者實作變更為 EmailSender
:
- builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
+ builder.Services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>();
IdentityNoOpEmailSender
從應用程式移除 (Components/Account/IdentityNoOpEmailSender.cs
)。
在元件 () 中RegisterConfirmation
,移除 區塊中的@code
條件式區塊,以檢查 是否EmailSender
為 IdentityNoOpEmailSender
:Components/Account/Pages/RegisterConfirmation.razor
- else if (EmailSender is IdentityNoOpEmailSender)
- {
- ...
- }
此外,在元件中 RegisterConfirmation
,移除 Razor 標記和程式代碼來檢查 emailConfirmationLink
字段,只留下一行指示使用者檢查其電子郵件...
- @if (emailConfirmationLink is not null)
- {
- ...
- }
- else
- {
<p>Please check your email to confirm your account.</p>
- }
@code {
- private string? emailConfirmationLink;
...
}
電子郵件和活動逾時
預設無活動逾時為 14 天。 下列程式代碼會將無活動逾時設定為5天,並具有滑動到期日:
builder.Services.ConfigureApplicationCookie(options => {
options.ExpireTimeSpan = TimeSpan.FromDays(5);
options.SlidingExpiration = true;
});
變更所有資料保護權杖生命週期
下列程式碼會將所有資料保護權杖逾時期間變更為 3 小時:
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
options.TokenLifespan = TimeSpan.FromHours(3));
內 Identity 建的使用者令牌 (AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs) 有一 天的逾時。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
變更電子郵件權杖生命週期
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
若要變更電子郵件權杖生命週期,請新增自訂 DataProtectorTokenProvider<TUser> 和 DataProtectionTokenProviderOptions:
CustomTokenProvider.cs
:
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
namespace BlazorSample;
public class CustomEmailConfirmationTokenProvider<TUser>
: DataProtectorTokenProvider<TUser> where TUser : class
{
public CustomEmailConfirmationTokenProvider(
IDataProtectionProvider dataProtectionProvider,
IOptions<EmailConfirmationTokenProviderOptions> options,
ILogger<DataProtectorTokenProvider<TUser>> logger)
: base(dataProtectionProvider, options, logger)
{
}
}
public class EmailConfirmationTokenProviderOptions
: DataProtectionTokenProviderOptions
{
public EmailConfirmationTokenProviderOptions()
{
Name = "EmailDataProtectorTokenProvider";
TokenLifespan = TimeSpan.FromHours(4);
}
}
public class CustomPasswordResetTokenProvider<TUser>
: DataProtectorTokenProvider<TUser> where TUser : class
{
public CustomPasswordResetTokenProvider(
IDataProtectionProvider dataProtectionProvider,
IOptions<PasswordResetTokenProviderOptions> options,
ILogger<DataProtectorTokenProvider<TUser>> logger)
: base(dataProtectionProvider, options, logger)
{
}
}
public class PasswordResetTokenProviderOptions :
DataProtectionTokenProviderOptions
{
public PasswordResetTokenProviderOptions()
{
Name = "PasswordResetDataProtectorTokenProvider";
TokenLifespan = TimeSpan.FromHours(3);
}
}
設定服務以在檔案中使用 Program
自訂權杖提供者:
builder.Services.AddIdentityCore<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.Tokens.ProviderMap.Add("CustomEmailConfirmation",
new TokenProviderDescriptor(
typeof(CustomEmailConfirmationTokenProvider<ApplicationUser>)));
options.Tokens.EmailConfirmationTokenProvider =
"CustomEmailConfirmation";
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
builder.Services
.AddTransient<CustomEmailConfirmationTokenProvider<ApplicationUser>>();
疑難排解
如果您無法讓電子郵件運作:
- 在
EmailSender.Execute
中設定中斷點以確認SendEmailAsync
已呼叫。 - 建立主控台應用程式,以使用類似
EmailSender.Execute
對問題進行偵錯的程式代碼來傳送電子郵件。 - 檢閱電子郵件提供者網站上的帳戶電子郵件記錄頁面。
- 檢查您的垃圾郵件資料夾是否有郵件。
- 在不同的電子郵件提供者上嘗試另一個電子郵件別名,例如 Microsoft、Yahoo 或 Gmail。
- 請嘗試傳送至不同的電子郵件帳戶。
警告
請勿在測試和開發中使用生產秘密。 如果您將應用程式發佈至 Azure,請在 Azure Web 應用程式入口網站中將秘密設定為應用程式設定。 設定系統已設為從環境變數讀取金鑰。
在網站有使用者之後啟用帳戶確認
在有使用者的網站上啟用帳戶確認,會鎖定所有現有的使用者。 現有的使用者因為未確認其帳戶而遭到鎖定。 若要解決現有的使用者鎖定問題,請使用下列其中一種方法:
- 更新資料庫,將所有現有的用戶標示為已確認。
- 確認現有的使用者。 例如,批次傳送具有確認連結的電子郵件。
其他資源
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應