Udostępnij za pośrednictwem


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

W tym artykule wyjaśniono, jak skonfigurować aplikację internetową ASP.NET Core Blazor z potwierdzeniem wiadomości e-mail i odzyskiwaniem hasła.

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ę, aby pobrać bezpieczny klucz interfejsu API 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:

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

Ustaw klucz za pomocą narzędzia secret-manager. W poniższym przykładzie nazwa klucza to EmailAuthKey , a klucz jest reprezentowany przez {KEY} symbol zastępczy. W powłoce poleceń przejdź do folderu głównego aplikacji i wykonaj następujące polecenie przy użyciu klucza interfejsu API:

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

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

Zaimplementować IEmailSender

Zaimplementuj IEmailSender dla dostawcy. 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 komunikatu w metodzie 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);
    }
}

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, zapoznaj się z dokumentacją dostawcy usług.

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;

     ...
}

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 5 dni z przesuwanym wygaśnięciem:

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

Zmienianie wszystkich cykli życia tokenu ochrony danych

Poniższy kod zmienia limit czasu wszystkich tokenów ochrony danych na 3 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.

Ostrzeżenie

Nie używaj wpisów tajnych produkcyjnych w środowisku testowym i programistycznym. Jeśli opublikujesz aplikację na platformie Azure, ustaw wpisy tajne jako ustawienia aplikacji w portalu aplikacji internetowej platformy Azure. System konfiguracji jest skonfigurowany do odczytu kluczy ze zmiennych środowiskowych.

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.

Dodatkowe zasoby