Udostępnij za pośrednictwem


Potwierdzenie konta i odzyskiwanie hasła w usłudze ASP.NET Core Blazor

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.

W tym artykule wyjaśniono, jak skonfigurować ASP.NET Core Blazor Web App przy użyciu potwierdzenia wiadomości e-mail i odzyskiwania hasła.

Uwaga

Ten artykuł dotyczy Blazor Web Apptylko s. Aby zaimplementować potwierdzenie wiadomości e-mail i odzyskiwanie haseł dla autonomicznych Blazor WebAssembly aplikacji za pomocą platformy ASP.NET Core Identity, zobacz Potwierdzanie konta i odzyskiwanie hasła w programie ASP.NET Core Blazor WebAssembly za pomocą platformy ASP.NET Core Identity.

Przestrzeń nazw

Przestrzeń nazw aplikacji używana przez przykład w tym artykule to BlazorSample. Zaktualizuj przykłady kodu, aby używać przestrzeni nazw aplikacji.

Wybieranie i konfigurowanie dostawcy poczty e-mail

W tym artykule interfejs API transakcyjny mailchimpa jest używany za pośrednictwem Mandrill.net do wysyłania wiadomości e-mail. Zalecamy używanie usługi poczty e-mail do wysyłania wiadomości e-mail zamiast SMTP. Protokół SMTP jest trudny do prawidłowego konfigurowania i zabezpieczania. Niezależnie od używanej usługi poczty e-mail uzyskaj dostęp do wskazówek dotyczących aplikacji platformy .NET, utwórz konto, skonfiguruj klucz interfejsu API dla swojej usługi i zainstaluj wymagane pakiety NuGet.

Utwórz klasę do przechowywania klucza interfejsu API tajnego dostawcy poczty e-mail. W przykładzie w tym artykule użyto klasy o nazwie AuthMessageSenderOptions z właściwością EmailAuthKey do przechowywania klucza.

AuthMessageSenderOptions.cs:

namespace BlazorSample;

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

AuthMessageSenderOptions Zarejestruj wystąpienie konfiguracji w Program pliku:

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

Konfigurowanie wpisu tajnego użytkownika dla klucza zabezpieczeń dostawcy

Jeśli projekt został już zainicjowany dla narzędzia Secret Manager, będzie on już miał identyfikator wpisów tajnych aplikacji () w pliku projektu (.csproj<AppSecretsId>). W programie Visual Studio możesz określić, czy identyfikator wpisów tajnych aplikacji jest obecny, przeglądając panel Właściwości po wybraniu projektu w Eksplorator rozwiązań. Jeśli aplikacja nie została zainicjowana, wykonaj następujące polecenie w powłoce poleceń otwartej w katalogu projektu. W programie Visual Studio możesz użyć wiersza polecenia Programu PowerShell dla deweloperów.

dotnet user-secrets init

Ustaw klucz interfejsu API za pomocą narzędzia Secret Manager. W poniższym przykładzie nazwa klucza jest EmailAuthKey zgodna AuthMessageSenderOptions.EmailAuthKeyz symbolem zastępczym , a klucz jest reprezentowany {KEY} przez symbol zastępczy. Wykonaj następujące polecenie za pomocą klucza interfejsu API:

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

Jeśli używasz programu Visual Studio, możesz potwierdzić, że wpis tajny został ustawiony, klikając prawym przyciskiem myszy projekt serwera w Eksplorator rozwiązań i wybierając polecenie Zarządzaj wpisami tajnymi użytkownika.

Aby uzyskać więcej informacji, zobacz Bezpieczny magazyn wpisów tajnych aplikacji w programowaniu w usłudze ASP.NET Core.

Ostrzeżenie

Nie przechowuj wpisów tajnych aplikacji, parametry połączenia, poświadczeń, haseł, osobistych numerów identyfikacyjnych (PIN), prywatnego kodu C#/.NET lub kluczy prywatnych/tokenów w kodzie po stronie klienta, który jest zawsze niepewny. W środowiskach testowych/przejściowych i produkcyjnych kod po stronie Blazor serwera i internetowe interfejsy API powinny używać bezpiecznych przepływów uwierzytelniania, które unikają utrzymywania poświadczeń w kodzie projektu lub plikach konfiguracji. Poza lokalnymi testami programistycznymi zalecamy unikanie używania zmiennych środowiskowych do przechowywania poufnych danych, ponieważ zmienne środowiskowe nie są najbezpieczniejszym podejściem. W przypadku lokalnego testowania programistycznego narzędzie Secret Manager jest zalecane do zabezpieczania poufnych danych. Aby uzyskać więcej informacji, zobacz Bezpieczne utrzymywanie poufnych danych i poświadczeń.

Narzędzie IEmailSender

Poniższy przykład jest oparty na interfejsie API transakcyjnym Mailchimp przy użyciu Mandrill.net. W przypadku innego dostawcy zapoznaj się z dokumentacją dotyczącą implementowania wysyłania wiadomości e-mail.

Dodaj pakiet Mandrill.net NuGet do projektu.

Dodaj następującą EmailSender klasę, aby zaimplementować element IEmailSender<TUser>. W poniższym przykładzie ApplicationUser jest to IdentityUser. Adiustacja HTML komunikatu może być dodatkowo dostosowywana. O ile przekazany MandrillMessage element message zaczyna się od < znaku, interfejs API Mandrill.net zakłada, że treść komunikatu jest skomponowana w kodzie 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);
    }
}

Uwaga

Zawartość treści wiadomości może wymagać specjalnego kodowania dla dostawcy usługi poczty e-mail. Jeśli nie można wykonać linków w treści wiadomości e-mail, zapoznaj się z dokumentacją dostawcy usług, aby rozwiązać ten problem.

Konfigurowanie aplikacji do obsługi poczty e-mail

Program W pliku zmień implementację nadawcy wiadomości e-mail na :EmailSender

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

Usuń element IdentityNoOpEmailSender (Components/Account/IdentityNoOpEmailSender.cs) z aplikacji.

W składniku RegisterConfirmation (Components/Account/Pages/RegisterConfirmation.razor) usuń blok warunkowy w @code bloku, który sprawdza, czy EmailSender element to IdentityNoOpEmailSender:

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

Ponadto w składniku RegisterConfirmation usuń Razor znaczniki i kod sprawdzania emailConfirmationLink pola, pozostawiając tylko wiersz instruujący użytkownika, aby sprawdzić swoją wiadomość e-mail...

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

@code {
-    private string? emailConfirmationLink;

     ...
}

Włączanie potwierdzenia konta po tym, jak witryna ma użytkowników

Włączanie potwierdzenia konta w witrynie z użytkownikami blokuje wszystkich istniejących użytkowników. Istniejący użytkownicy są zablokowani, ponieważ ich konta nie są potwierdzane. Aby obejść istniejącą blokadę użytkownika, użyj jednej z następujących metod:

  • Zaktualizuj bazę danych, aby oznaczyć wszystkich istniejących użytkowników zgodnie z potwierdzeniem.
  • Potwierdź istniejących użytkowników. Na przykład wiadomości e-mail wysyłane wsadowo z linkami potwierdzenia.

Limit czasu wiadomości e-mail i aktywności

Domyślny limit czasu braku aktywności wynosi 14 dni. Poniższy kod ustawia limit czasu braku aktywności na pięć dni z przesuwanym wygaśnięciem:

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

Zmiana wszystkich cykli życia tokenu ASP.NET Core Data Protection

Poniższy kod zmienia limit czasu tokenów ochrony danych na trzy godziny:

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

Wbudowane Identity tokeny użytkownika (AspNetCore/src//IdentityExtensions.Core/src/TokenOptions.cs) mają jednorazowy limit czasu.

Uwaga

Linki dokumentacji do źródła referencyjnego platformy .NET zwykle ładują domyślną gałąź repozytorium, która odzwierciedla bieżące programowanie dla następnej wersji platformy .NET. Aby wybrać tag dla określonej wersji, użyj listy rozwijanej Przełącz gałęzie lub tagi. Aby uzyskać więcej informacji, zobacz Jak wybrać tag wersji kodu źródłowego platformy ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Zmienianie cyklu życia tokenu poczty e-mail

Domyślna żywotność tokenów Identity użytkownika wynosi jeden dzień.

Uwaga

Linki dokumentacji do źródła referencyjnego platformy .NET zwykle ładują domyślną gałąź repozytorium, która odzwierciedla bieżące programowanie dla następnej wersji platformy .NET. Aby wybrać tag dla określonej wersji, użyj listy rozwijanej Przełącz gałęzie lub tagi. Aby uzyskać więcej informacji, zobacz Jak wybrać tag wersji kodu źródłowego platformy ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Aby zmienić cykl życia tokenu poczty e-mail, dodaj element niestandardowy DataProtectorTokenProvider<TUser> i 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);
    }
}

Skonfiguruj usługi tak, aby korzystały z niestandardowego dostawcy tokenów Program w pliku:

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

Rozwiązywanie problemów

Jeśli nie możesz uzyskać wiadomości e-mail, działa:

  • Ustaw punkt przerwania w , EmailSender.Execute aby zweryfikować SendEmailAsync , jest wywoływany.
  • Utwórz aplikację konsolową do wysyłania wiadomości e-mail przy użyciu kodu podobnego do EmailSender.Execute debugowania problemu.
  • Przejrzyj strony historii poczty e-mail konta w witrynie internetowej dostawcy poczty e-mail.
  • Sprawdź folder spamu pod kątem wiadomości.
  • Spróbuj użyć innego aliasu poczty e-mail u innego dostawcy poczty e-mail, takiego jak Microsoft, Yahoo lub Gmail.
  • Spróbuj wysłać do różnych kont e-mail.

Dodatkowe zasoby