Potvrzení účtu a obnovení hesla v ASP.NET Core Blazor
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Tento článek vysvětluje, jak nakonfigurovat ASP.NET Core Blazor Web App s potvrzením e-mailu a obnovením hesla.
Poznámka:
Tento článek se týká Blazor Web Apppouze s. Pokud chcete implementovat potvrzení e-mailu a obnovení hesla pro samostatné Blazor WebAssembly aplikace s ASP.NET Core Identity, přečtěte si informace o potvrzení účtu a obnovení hesla v ASP.NET Core Blazor WebAssembly s ASP.NET Core Identity.
Obor názvů
Obor názvů aplikace používaný v příkladu v tomto článku je BlazorSample
. Aktualizujte příklady kódu tak, aby používaly obor názvů vaší aplikace.
Výběr a konfigurace poskytovatele e-mailu
V tomto článku se k odesílání e-mailů používá transakční rozhraní API mailchimpu prostřednictvím Mandrill.net . K odesílání e-mailů místo SMTP doporučujeme použít e-mailovou službu. Konfigurace a zabezpečení protokolu SMTP je obtížné. Bez ohledu na to, kterou e-mailovou službu používáte, získejte přístup k pokynům pro aplikace .NET, vytvořte účet, nakonfigurujte klíč rozhraní API pro svou službu a nainstalujte všechny požadované balíčky NuGet.
Vytvořte třídu pro uložení klíče rozhraní API zprostředkovatele tajných e-mailů. Příklad v tomto článku používá třídu pojmenovanou AuthMessageSenderOptions
EmailAuthKey
s vlastností k uložení klíče.
AuthMessageSenderOptions.cs
:
namespace BlazorSample;
public class AuthMessageSenderOptions
{
public string? EmailAuthKey { get; set; }
}
AuthMessageSenderOptions
Zaregistrujte instanci konfigurace v Program
souboru:
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
Konfigurace tajného klíče pro klíč zabezpečení poskytovatele e-mailu
Od poskytovatele obdržíte klíč zabezpečení poskytovatele e-mailu a použijete ho v následujících doprovodných materiálech.
K poskytnutí tajného kódu aplikaci použijte jeden nebo oba následující přístupy:
- nástroj Secret Manager: Nástroj Secret Manager ukládá soukromá data na místním počítači a používá se pouze při místním vývoji.
- cs-CZ: Azure Key Vault: Tajemství můžete uložit do Azure Key Vault pro použití v libovolném prostředí, včetně vývojového prostředí při práci lokálně. Někteří vývojáři raději používají trezory klíčů pro přípravné a produkční nasazení a používají nástroj Secret Manager pro místní vývoj.
Důrazně doporučujeme, abyste se vyhnuli ukládání tajných kódů do kódu projektu nebo konfiguračních souborů. Používejte zabezpečené ověřovací toky, jako jsou oba přístupy v této části.
Nástroj Secret Manager
Pokud už byl projekt inicializován pro .csproj
V sadě Visual Studio zjistíte, jestli id tajných kódů aplikace existuje, a to tak, že se podíváte na panel Vlastnosti, když je projekt vybraný v Průzkumník řešení. Pokud aplikace nebyla inicializována, spusťte v příkazovém prostředí otevřeném v adresáři projektu následující příkaz. V sadě Visual Studio můžete použít příkazový řádek Developer PowerShellu.
dotnet user-secrets init
Nastavte klíč rozhraní API pomocí nástroje Secret Manager. V následujícím příkladu se název klíče shoduje EmailAuthKey
AuthMessageSenderOptions.EmailAuthKey
a klíč je reprezentován zástupným {KEY}
symbolem. Spusťte následující příkaz s klíčem rozhraní API:
dotnet user-secrets set "EmailAuthKey" "{KEY}"
Pokud používáte Visual Studio, můžete ověřit, že je tajný kód nastavený tak, že v Průzkumník řešení kliknete pravým tlačítkem na projekt serveru a vyberete Spravovat tajné kódy uživatelů.
Další informace najdete v tématu Bezpečné ukládání tajných kódů aplikací při vývoji v ASP.NET Core.
Upozorňující
Neukládejte tajné kódy aplikací, připojovací řetězec, přihlašovací údaje, hesla, osobní identifikační čísla (PIN), privátní kód C#/.NET nebo privátní klíče/tokeny v kódu na straně klienta, což je vždy nezabezpečené. V testovacích a pracovních a produkčních prostředích by kód na straně Blazor serveru a webová rozhraní API měly používat toky zabezpečeného ověřování, které se vyhýbají údržbě přihlašovacích údajů v kódu projektu nebo konfiguračních souborech. Mimo místní testování vývoje doporučujeme vyhnout se použití proměnných prostředí k ukládání citlivých dat, protože proměnné prostředí nejsou nejbezpečnějším přístupem. Pro místní testování vývoje se pro zabezpečení citlivých dat doporučuje nástroj Secret Manager. Další informace najdete v tématu Bezpečné udržování citlivých dat a přihlašovacích údajů.
Azure Key Vault
Azure Key Vault poskytuje bezpečný způsob předání klientského tajemství aplikace.
Pokud chcete vytvořit trezor klíčů a nastavit tajný klíč, přečtěte si téma Informace o tajných klíčích služby Azure Key Vault (dokumentace k Azure), které křížově propojí prostředky, které vám pomůžou začít se službou Azure Key Vault. Pokud chcete implementovat kód v této části, poznamenejte si identifikátor URI trezoru klíčů a název tajného kódu z Azure při vytváření trezoru klíčů a tajného klíče. Když nastavíte zásady přístupu pro tajemství na panelu Zásady přístupu:
- Je vyžadováno pouze tajné oprávnění k získání.
- Jako hlavní pro tajný klíč vyberte aplikaci.
Ověřte na portálu Azure nebo Entra, že aplikace má udělený přístup k tajnému kódu, který jste vytvořili pro klíč poskytovatele e-mailu.
Důležité
Vytvoří se tajný klíč trezoru klíčů s datem vypršení platnosti. Nezapomeňte sledovat, kdy vyprší platnost tajemství v trezoru klíčů, a vytvořte pro aplikaci nové tajemství před tímto datem.
Do projektu serveru přidejte následující třídu AzureHelper
. Metoda GetKeyVaultSecret
načte tajný kód z trezoru klíčů. Upravte obor názvů (BlazorSample.Helpers
) tak, aby odpovídal schématu oboru názvů projektu.
Helpers/AzureHelper.cs
:
using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace BlazorSample.Helpers;
public static class AzureHelper
{
public static string GetKeyVaultSecret(string tenantId, string vaultUri, string secretName)
{
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = tenantId,
SharedTokenCacheTenantId = tenantId
};
var client = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(options));
var secret = client.GetSecretAsync(secretName).Result;
return secret.Value.Value;
}
}
Kde jsou služby zaregistrovány v souboru Program
projektu serveru, získejte a vážte tajný klíč s konfigurací Možnosti.
var tenantId = builder.Configuration.GetValue<string>("AzureAd:TenantId")!;
var vaultUri = builder.Configuration.GetValue<string>("AzureAd:VaultUri")!;
var emailAuthKey = AzureHelper.GetKeyVaultSecret(
tenantId, vaultUri, "EmailAuthKey");
var authMessageSenderOptions =
new AuthMessageSenderOptions() { EmailAuthKey = emailAuthKey };
builder.Configuration.GetSection(authMessageSenderOptions.EmailAuthKey)
.Bind(authMessageSenderOptions);
Pokud chcete řídit prostředí, ve kterém funguje předchozí kód, například abyste se vyhnuli místnímu spuštění kódu, protože jste se rozhodli použít nástroj Secret Manager pro místní vývoj, můžete předchozí kód zabalit do podmíněného příkazu, který kontroluje prostředí:
if (!context.HostingEnvironment.IsDevelopment())
{
...
}
V části AzureAd
appsettings.json
v serverovém projektu potvrďte přítomnost Entra ID aplikace TenantId
a přidejte následující konfigurační klíč a hodnotu VaultUri
, pokud tam ještě nejsou.
"VaultUri": "{VAULT URI}"
V předchozím příkladu je zástupný symbol {VAULT URI}
URI klíčového trezoru. Zahrňte lomítko na konci adresy URI.
Příklad:
"VaultUri": "https://contoso.vault.azure.net/"
Konfigurace se používá k usnadnění poskytování vyhrazených trezorů klíčů a názvů tajných kódů na základě konfiguračních souborů prostředí aplikace. Můžete například zadat různé hodnoty konfigurace pro appsettings.Development.json
ve vývoji, appsettings.Staging.json
při přípravě a appsettings.Production.json
pro produkční nasazení. Další informace o konfiguraci ASP.NET Corenajdete v Blazor.
Implementovat IEmailSender
Následující příklad je založený na transakčním rozhraní API mailchimpu pomocí Mandrill.net. Informace o tom, jak implementovat odesílání e-mailových zpráv, najdete v dokumentaci jiného poskytovatele.
Přidejte do projektu balíček NuGet Mandrill.net .
Přidejte následující EmailSender
třídu pro implementaci IEmailSender<TUser>. V následujícím příkladu ApplicationUser
je .IdentityUser Kód HTML zprávy lze dále přizpůsobit. Pokud message
MandrillMessage
předání začíná znakem <
, Mandrill.net ROZHRANÍ API předpokládá, že text zprávy se skládá v HTML.
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(AppUser user, string email,
string confirmationLink) => SendEmailAsync(email, "Confirm your email",
"<html lang=\"en\"><head></head><body>Please confirm your account by " +
$"<a href='{confirmationLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetLinkAsync(AppUser user, string email,
string resetLink) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password by " +
$"<a href='{resetLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetCodeAsync(AppUser user, string email,
string resetCode) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password " +
$"using the following code:<br>{resetCode}</body></html>");
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);
}
}
Poznámka:
Základní obsah zpráv může vyžadovat speciální kódování pro poskytovatele e-mailové služby. Pokud odkazy v textu zprávy nelze v e-mailové zprávě sledovat, obraťte se na dokumentaci poskytovatele služeb a problém vyřešte.
Konfigurace aplikace pro podporu e-mailu
Program
V souboru změňte implementaci odesílatele e-mailu na EmailSender
:
- builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
+ builder.Services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>();
IdentityNoOpEmailSender
Odeberte (Components/Account/IdentityNoOpEmailSender.cs
) z aplikace.
V komponentě RegisterConfirmation
(Components/Account/Pages/RegisterConfirmation.razor
) odeberte podmíněný blok v @code
bloku, který zkontroluje, zda EmailSender
je IdentityNoOpEmailSender
:
- else if (EmailSender is IdentityNoOpEmailSender)
- {
- ...
- }
Také v komponentě RegisterConfirmation
odeberte značky Razor a kód pro kontrolu emailConfirmationLink
pole a ponechte jen řádek s pokynem uživateli, aby zkontroloval svůj e-mail ...
- @if (emailConfirmationLink is not null)
- {
- ...
- }
- else
- {
<p>Please check your email to confirm your account.</p>
- }
@code {
- private string? emailConfirmationLink;
...
}
Povolení potvrzení účtu po tom, co má web uživatele
Povolení potvrzení účtu na webu s uživateli zamkne všechny stávající uživatele. Stávající uživatelé jsou uzamčení, protože jejich účty se nepotvrdí. Pokud chcete obejít stávající uzamčení uživatele, použijte jeden z následujících přístupů:
- Aktualizujte databázi tak, aby označí všechny existující uživatele jako potvrzené.
- Potvrďte existující uživatele. Například dávkové odesílání e-mailů s potvrzovanými odkazy.
Vypršení časového limitu e-mailu a aktivity
Výchozí časový limit nečinnosti je 14 dnů. Následující kód nastaví časový limit nečinnosti na pět dnů s posuvným vypršením platnosti:
builder.Services.ConfigureApplicationCookie(options => {
options.ExpireTimeSpan = TimeSpan.FromDays(5);
options.SlidingExpiration = true;
});
Změna všech životností tokenů ochrany dat core ASP.NET
Následující kód změní časový limit tokenů ochrany dat na tři hodiny:
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
options.TokenLifespan = TimeSpan.FromHours(3));
Předdefinované Identity uživatelské tokeny (AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs) mají časový limit jednoho dne.
Poznámka:
Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Změna životnosti e-mailového tokenu
Výchozí životnost Identity tokenů uživatele je jeden den.
Poznámka:
Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Pokud chcete změnit životnost e-mailového tokenu, přidejte vlastní DataProtectorTokenProvider<TUser> a 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);
}
}
Nakonfigurujte služby tak, aby používaly vlastního zprostředkovatele tokenu Program
v souboru:
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>>();
Odstraňování potíží
Pokud vám nefunguje e-mail:
- Nastavte zarážku
EmailSender.Execute
pro ověřeníSendEmailAsync
. - Vytvořte konzolovou aplikaci pro odesílání e-mailů pomocí kódu podobného
EmailSender.Execute
ladění problému. - Zkontrolujte stránky historie e-mailů účtu na webu poskytovatele e-mailu.
- Zkontrolujte, jestli ve složce spamu nezískáte zprávy.
- Zkuste jiný e-mailový alias u jiného poskytovatele e-mailu, jako je Microsoft, Yahoo nebo Gmail.
- Zkuste odeslat do různých e-mailových účtů.