Sdílet prostřednictvím


Potvrzení účtu a obnovení hesla v ASP.NET Core Blazor

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

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 AuthMessageSenderOptionsEmailAuthKey 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 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 EmailAuthKeyAuthMessageSenderOptions.EmailAuthKeya 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. V příkladu v této části je tajný název "EmailAuthKey."

Při vytváření trezoru klíčů na webu Entra nebo Azure Portal:

  • Nakonfigurujte trezor klíčů tak, aby používal řízení přístupu na základě role v Azure (RABC). Pokud nepracujete na Azure Virtual Network, včetně místního vývoje a testování, ověřte, že je ve veřejném přístupu v kroku Sítěpovoleno (zaškrtnuto). Povolení veřejného přístupu zveřejňuje jenom koncový bod trezoru klíčů. Pro přístup se stále vyžadují ověřené účty.

  • Vytvořte spravovanou Identity službu Azure (nebo přidejte roli do existujícího spravovaného Identity , kterou plánujete použít) s rolí uživatele tajných kódů služby Key Vault . Přiřaďte spravované Identity službě Azure App Service, která hostuje nasazení: Nastavení>Identity>Uživatelem přiřazené>Přidat.

    Poznámka:

    Pokud máte také v úmyslu spustit aplikaci místně s autorizovaným uživatelem pro přístup k trezoru klíčů pomocí Azure CLI nebo ověřování služby Azure sady Visual Studio, přidejte svůj uživatelský účet Azure pro vývojáře do řízení přístupu (IAM) s rolí Uživatele tajných kódů služby Key Vault . Pokud chcete použít Azure CLI prostřednictvím Visual Studio, spusťte az login příkaz z panelu Developer PowerShellu a postupujte podle pokynů k ověření nájemce.

Pokud chcete implementovat kód v této části, při vytváření trezoru klíčů a tajného klíče, z Azure si poznamenejte identifikátor URI trezoru klíčů (například "https://contoso.vault.azure.net/", vyžadováno koncové lomítko) a název tajného klíče (například "EmailAuthKey").

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.Core;
using Azure.Security.KeyVault.Secrets;

namespace BlazorSample.Helpers;

public static class AzureHelper
{
    public static string GetKeyVaultSecret(string vaultUri, 
        TokenCredential credential, string secretName)
    {
        var client = new SecretClient(new Uri(vaultUri), credential);
        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.

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

var emailAuthKey = AzureHelper.GetKeyVaultSecret("{VAULT URI}", credential, 
    "EmailAuthKey");

var authMessageSenderOptions = 
    new AuthMessageSenderOptions() { EmailAuthKey = emailAuthKey };
builder.Configuration.GetSection(authMessageSenderOptions.EmailAuthKey)
    .Bind(authMessageSenderOptions);

Poznámka:

V neprodukčních prostředích se předchozí příklad používá DefaultAzureCredential ke zjednodušení ověřování při vývoji aplikací, které se nasazují do Azure zkombinováním přihlašovacích údajů používaných v hostitelských prostředích Azure s přihlašovacími údaji použitými v místním vývoji. Další informace najdete v tématu Ověřování aplikací .NET hostovaných v Azure v prostředcích Azure pomocí spravované identity přiřazené systémem.

Předchozí příklad naznačuje, že ID spravovaného klienta (Identity), ID adresáře (tenanta) ({MANAGED IDENTITY CLIENT ID}), a identifikátor URI trezoru klíčů ({TENANT ID}, příklad: {VAULT URI}, s vyžadovaným koncovým lomítkem) jsou zadány pevně zakódovanými hodnotami. Jakékoli nebo všechny tyto hodnoty je možné zadat z konfigurace nastavení aplikace. Například následující kód získá URI trezoru z uzlu AzureAd souboru nastavení aplikace a při volání vaultUri v předchozím příkladu lze použít GetKeyVaultSecret.

var vaultUri = builder.Configuration.GetValue<string>("AzureAd:VaultUri")!;

Další informace o konfiguraci Blazornajdete v .

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 messageMandrillMessage 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ů.

Další materiály