Freigeben über


Kontobestätigung und Kennwortwiederherstellung in ASP.NET Core Blazor

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.

In diesem Artikel wird erläutert, wie Sie eine ASP.NET Core-Blazor Web App mit E-Mail-Bestätigung und Kennwortwiederherstellung konfigurieren.

Hinweis

Dieser Artikel gilt nur für Blazor Web Apps. Informationen zum Implementieren der E-Mail-Bestätigung und kennwortwiederherstellung für eigenständige Blazor WebAssembly Apps mit ASP.NET Core Identityfinden Sie unter Kontobestätigung und Kennwortwiederherstellung in ASP.NET Core Blazor WebAssembly mit ASP.NET Core Identity.

Namespace

Im Beispiel in diesem Artikel wird der App-Namespace BlazorSample verwendet. Aktualisieren Sie die Codebeispiele, um den Namespace Ihrer App zu verwenden.

Auswählen und Konfigurieren eines E-Mail-Anbieters

In diesem Artikel wird die Transactional API von Mailchimp über Mandrill.net zum Senden von E-Mails verwendet. Es wird empfohlen, einen E-Mail-Dienst statt SMTP zum Senden von E-Mails zu verwenden. SMTP ist schwer zu konfigurieren und zu schützen. Je nachdem, welchen E-Mail-Dienst Sie verwenden, befolgen Sie dessen Anleitungen für .NET-Apps, erstellen ein Konto, konfigurieren einen API-Schlüssel für den Dienst und installieren alle erforderlichen NuGet-Pakete.

Erstellen Sie eine Klasse, um den geheimen E-Mail-Anbieter-API-Schlüssel zu halten. Im Beispiel in diesem Artikel wird eine Klasse mit einem Namen AuthMessageSenderOptions mit einer EmailAuthKey Eigenschaft verwendet, um den Schlüssel zu halten.

AuthMessageSenderOptions.cs:

namespace BlazorSample;

public class AuthMessageSenderOptions
{
    public string? EmailAuthKey { get; set; }
}

Registrieren Sie die AuthMessageSenderOptions-Konfigurationsinstanz in der Program-Datei:

builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);

Konfigurieren eines Benutzergeheimnisses für den Sicherheitsschlüssel des Anbieters

Wenn das Projekt bereits für das Tool "Geheimer Manager" initialisiert wurde, verfügt es bereits über einen geheimen App-Bezeichner (<AppSecretsId>) in der Projektdatei (.csproj). In Visual Studio können Sie feststellen, ob die ID der geheimen App vorhanden ist, indem Sie sich den Eigenschaftenbereich ansehen, wenn das Projekt in Projektmappen-Explorer ausgewählt ist. Wenn die App nicht initialisiert wurde, führen Sie den folgenden Befehl in einer Befehlsshell aus, die im Verzeichnis des Projekts geöffnet wurde. In Visual Studio können Sie die PowerShell-Eingabeaufforderung für Entwickler verwenden.

dotnet user-secrets init

Legen Sie den API-Schlüssel mit dem Tool "Geheimer Manager" fest. Im folgenden Beispiel muss EmailAuthKey der Schlüsselname übereinstimmen AuthMessageSenderOptions.EmailAuthKey, und der Schlüssel wird durch den {KEY} Platzhalter dargestellt. Führen Sie den folgenden Befehl mit dem API-Schlüssel aus:

dotnet user-secrets set "EmailAuthKey" "{KEY}"

Wenn Sie Visual Studio verwenden, können Sie bestätigen, dass der geheime Schlüssel festgelegt ist, indem Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Serverprojekt klicken und "Benutzergeheimnisse verwalten" auswählen.

Weitere Informationen finden Sie unter Sichere Speicherung von App-Geheimnissen bei der Entwicklung in ASP.NET Core.

Warnung

Speichern Sie keine geheimen App-Schlüssel, Verbindungszeichenfolge s, Anmeldeinformationen, Kennwörter, persönliche Identifikationsnummern (PINs), privaten C#/.NET-Code oder private Schlüssel/Token im clientseitigen Code, der immer unsicher ist. In Test-/Staging- und Produktionsumgebungen sollten serverseitiger Blazor Code und Web-APIs sichere Authentifizierungsflüsse verwenden, die die Authentifizierung von Anmeldeinformationen innerhalb von Projektcode- oder Konfigurationsdateien vermeiden. Außerhalb der lokalen Entwicklungstests wird empfohlen, die Verwendung von Umgebungsvariablen zum Speichern vertraulicher Daten zu vermeiden, da Umgebungsvariablen nicht der sicherste Ansatz sind. Für lokale Entwicklungstests wird das Tool "Geheimer Manager" zum Sichern vertraulicher Daten empfohlen. Weitere Informationen finden Sie unter "Sichere Verwaltung vertraulicher Daten und Anmeldeinformationen".

Implementieren Sie IEmailSender.

Das folgende Beispiel basiert auf der Transactional API von Mailchimp unter Verwendung von Mandrill.net. Informationen zum Implementieren des Sendens einer E-Mail-Nachricht finden Sie in der Dokumentation eines anderen Anbieters.

Fügen Sie dem Projekt das Mandrill.net NuGet-Paket hinzu.

Fügen Sie die folgende EmailSender Klasse hinzu, um sie zu implementieren IEmailSender<TUser>. Im folgenden Beispiel ApplicationUser ist ein IdentityUser. Das HTML-Markup für Nachrichten kann weiter angepasst werden. Solange der message übergebene Wert MandrillMessage mit dem < Zeichen beginnt, geht die Mandrill.net-API davon aus, dass der Nachrichtentext in HTML verfasst ist.

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);
    }
}

Hinweis

Textkörperinhalte für Nachrichten erfordern möglicherweise eine spezielle Codierung für den E-Mail-Dienstanbieter. Wenn Links im Nachrichtentext in der E-Mail-Nachricht nicht befolgt werden können, wenden Sie sich an die Dokumentation des Dienstanbieters, um das Problem zu beheben.

Konfigurieren der App zur Unterstützung von E-Mails

Ändern Sie in der Datei Program die Implementierung des E-Mail-Absenders in EmailSender:

- builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
+ builder.Services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>();

Entfernen Sie IdentityNoOpEmailSender (Components/Account/IdentityNoOpEmailSender.cs) aus der App.

Entfernen Sie in der Komponente RegisterConfirmation (Components/Account/Pages/RegisterConfirmation.razor) den Bedingungsblock aus dem @code-Block, der überprüft, ob EmailSender ein IdentityNoOpEmailSender-Element ist:

- else if (EmailSender is IdentityNoOpEmailSender)
- {
-     ...
- }

Entfernen Sie in der Komponente RegisterConfirmation ebenfalls das Razor-Markup und den Code zum Überprüfen des Felds emailConfirmationLink, und lassen Sie nur die Zeile, in der oder die Benutzer*in angewiesen wird, seine oder ihre E-Mail zu überprüfen.

- @if (emailConfirmationLink is not null)
- {
-     ...
- }
- else
- {
     <p>Please check your email to confirm your account.</p>
- }

@code {
-    private string? emailConfirmationLink;

     ...
}

Aktivieren der Kontobestätigung, nachdem eine Website Benutzer*innen enthält

Durch Aktivieren der Kontobestätigung auf einer Website mit Benutzer*innen werden alle vorhandenen Benutzer*innen gesperrt. Vorhandene Benutzer werden gesperrt, da ihre Konten nicht bestätigt wurden. Verwenden Sie einen der folgenden Ansätze, um die Sperrung vorhandener Benutzer*innen zu umgehen:

  • Aktualisieren Sie die Datenbank, um alle vorhandenen Benutzer*innen als bestätigt zu kennzeichnen.
  • Bestätigen Sie die vorhandenen Benutzer*innen. Senden Sie beispielsweise Batch-E-Mails mit Bestätigungslinks.

Timeout für E-Mails und Aktivitäten

Der Standardzeitraum für die Inaktivität bis zum Timeout beträgt 14 Tage. Der folgende Code legt das Inaktivitätstimeout auf fünf Tage mit variablem Ablauf fest:

builder.Services.ConfigureApplicationCookie(options => {
    options.ExpireTimeSpan = TimeSpan.FromDays(5);
    options.SlidingExpiration = true;
});

Ändern der Lebensdauer aller ASP.NET Core-Datenschutztoken

Der folgende Code ändert den Timeoutzeitraum für alle Datenschutztoken auf drei Stunden:

builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
    options.TokenLifespan = TimeSpan.FromHours(3));

Die integrierten Identity Benutzertoken (AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs) verfügen über ein Tagestimeout.

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Ändern der Lebensdauer von E-Mail-Token

Die Standardlebensdauer von Identity-Benutzertoken beträgt einen Tag.

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Um die Lebensdauer des E-Mail-Tokens zu ändern, fügen Sie eine benutzerdefinierte und DataProtectionTokenProviderOptionseine .DataProtectorTokenProvider<TUser>

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);
    }
}

Konfigurieren Sie die Dienste in der Datei Program für die Verwendung des benutzerdefinierten Tokenanbieters:

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>>();

Problembehandlung

Wenn E-Mails nicht funktionieren:

  • Legen Sie einen Breakpoint in EmailSender.Execute fest, um zu überprüfen, ob SendEmailAsync aufgerufen wird.
  • Erstellen Sie eine Konsolen-App, um E-Mails mithilfe von Code zu senden, der EmailSender.Execute zum Debuggen des Problems ähnelt.
  • Überprüfen Sie die E-Mail-Verlaufsseiten des Kontos auf der Website des E-Mail-Anbieters.
  • Überprüfen Sie Ihren Spamordner auf Nachrichten.
  • Versuchen Sie es mit einem anderen E-Mail-Alias bei einem anderen E-Mail-Anbieter, zum Beispiel Microsoft, Yahoo oder Gmail.
  • Versuchen Sie, die E-Mail an andere E-Mail-Konten zu senden.

Zusätzliche Ressourcen