Potwierdzenie konta i odzyskiwanie hasła w usłudze ASP.NET Core
Przez Rick Anderson, Ponant i Joe Audette
W tym samouczku pokazano, jak utworzyć aplikację ASP.NET Core z potwierdzeniem wiadomości e-mail i resetowaniem hasła. Ten samouczek nie jest tematem początkowym. Należy zapoznać się z:
Aby uzyskać Blazor wskazówki, które dodają lub zastępują wskazówki zawarte w tym artykule, zobacz Potwierdzanie konta i odzyskiwanie hasła w usłudze ASP.NET Core Blazor.
Wymagania wstępne
- Zestaw .NET Core 6.0 SDK lub nowszy
- Pomyślnie wyślij wiadomość e-mail z aplikacji konsolowej języka C#.
Tworzenie i testowanie aplikacji internetowej przy użyciu uwierzytelniania
Uruchom następujące polecenia, aby utworzyć aplikację internetową z uwierzytelnianiem.
dotnet new webapp -au Individual -o WebPWrecover
cd WebPWrecover
dotnet run
Rejestrowanie użytkownika przy użyciu symulowanego potwierdzenia wiadomości e-mail
Uruchom aplikację, wybierz link Zarejestruj i zarejestruj użytkownika. Po zarejestrowaniu /Identity/Account/RegisterConfirmation
nastąpi przekierowanie do strony zawierającej link do symulowania potwierdzenia wiadomości e-mail:
- Wybierz link
Click here to confirm your account
. - Wybierz link Zaloguj się i zaloguj się przy użyciu tych samych poświadczeń.
Hello YourEmail@provider.com!
Wybierz link, który przekierowuje do/Identity/Account/Manage/PersonalData
strony.- Wybierz kartę Dane osobowe po lewej stronie, a następnie wybierz pozycję Usuń.
Link Click here to confirm your account
jest wyświetlany, ponieważ element IEmailSender nie został zaimplementowany i zarejestrowany w kontenerze wstrzykiwania zależności. RegisterConfirmation
Zobacz źródło.
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).
Konfigurowanie dostawcy poczty e-mail
W tym samouczku usługa SendGrid służy do wysyłania wiadomości e-mail. Do wysyłania wiadomości e-mail jest wymagane konto i klucz usługi SendGrid. Zalecamy używanie usługi SendGrid lub innej usługi poczty e-mail do wysyłania wiadomości e-mail zamiast SMTP. Protokół SMTP jest trudny do zabezpieczenia i poprawnie skonfigurowany.
Konto usługi SendGrid może wymagać dodania nadawcy.
Utwórz klasę, aby pobrać bezpieczny klucz poczty e-mail. W tym przykładzie utwórz polecenie Services/AuthMessageSenderOptions.cs
:
namespace WebPWrecover.Services;
public class AuthMessageSenderOptions
{
public string? SendGridKey { get; set; }
}
Konfigurowanie wpisów tajnych użytkownika usługi SendGrid
Ustaw element SendGridKey
za pomocą narzędzia secret-manager. Na przykład:
dotnet user-secrets set SendGridKey <key>
Successfully saved SendGridKey to the secret store.
W systemie Windows menedżer wpisów tajnych przechowuje pary kluczy/wartości w secrets.json
pliku w %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId>
katalogu.
Zawartość secrets.json
pliku nie jest szyfrowana. Poniższy znacznik pokazuje secrets.json
plik. Wartość została usunięta SendGridKey
.
{
"SendGridKey": "<key removed>"
}
Aby uzyskać więcej informacji, zobacz Wzorzec i konfiguracja opcji.
Instalowanie usługi SendGrid
W tym samouczku pokazano, jak dodawać powiadomienia e-mail za pośrednictwem usługi SendGrid, ale mogą być używane inne dostawcy poczty e-mail.
SendGrid
Zainstaluj pakiet NuGet:
W konsoli Menedżer pakietów wprowadź następujące polecenie:
Install-Package SendGrid
Zobacz Wprowadzenie do usługi SendGrid bezpłatnie , aby zarejestrować się w celu uzyskania bezpłatnego konta usługi SendGrid.
Implementowanie usługi IEmailSender
Aby zaimplementować IEmailSender
metodę , utwórz Services/EmailSender.cs
za pomocą kodu podobnego do następującego:
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
namespace WebPWrecover.Services;
public class EmailSender : IEmailSender
{
private readonly ILogger _logger;
public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
ILogger<EmailSender> logger)
{
Options = optionsAccessor.Value;
_logger = logger;
}
public AuthMessageSenderOptions Options { get; } //Set with Secret Manager.
public async Task SendEmailAsync(string toEmail, string subject, string message)
{
if (string.IsNullOrEmpty(Options.SendGridKey))
{
throw new Exception("Null SendGridKey");
}
await Execute(Options.SendGridKey, subject, message, toEmail);
}
public async Task Execute(string apiKey, string subject, string message, string toEmail)
{
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage()
{
From = new EmailAddress("Joe@contoso.com", "Password Recovery"),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(toEmail));
// Disable click tracking.
// See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
var response = await client.SendEmailAsync(msg);
_logger.LogInformation(response.IsSuccessStatusCode
? $"Email to {toEmail} queued successfully!"
: $"Failure Email to {toEmail}");
}
}
Konfigurowanie aplikacji do obsługi poczty e-mail
Dodaj następujący kod do pliku Program.cs
:
- Dodaj
EmailSender
jako usługę przejściową. AuthMessageSenderOptions
Zarejestruj wystąpienie konfiguracji.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Wyłącz domyślną weryfikację konta, gdy element Account.RegisterConfirmation został utworzony szkieletem
Ta sekcja ma zastosowanie tylko w przypadku Account.RegisterConfirmation
tworzenia szkieletów. Pomiń tę sekcję, jeśli nie utworzono szkieletu Account.RegisterConfirmation
.
Użytkownik jest przekierowywany do Account.RegisterConfirmation
lokalizacji, w której może wybrać link, aby potwierdzić konto. Wartość domyślna Account.RegisterConfirmation
jest używana tylko do testowania, automatyczna weryfikacja konta powinna być wyłączona w aplikacji produkcyjnej.
Aby wymagać potwierdzonego konta i uniemożliwić natychmiastowe logowanie podczas rejestracji, ustaw DisplayConfirmAccountLink = false
w pliku szkieletowym /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;
namespace WebPWrecover.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IEmailSender _sender;
public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
{
_userManager = userManager;
_sender = sender;
}
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string Email { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public bool DisplayConfirmAccountLink { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
returnUrl = returnUrl ?? Url.Content("~/");
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
return NotFound($"Unable to load user with email '{email}'.");
}
Email = email;
// Once you add a real email sender, you should remove this code that lets you confirm the account
DisplayConfirmAccountLink = false;
if (DisplayConfirmAccountLink)
{
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
EmailConfirmationUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
}
return Page();
}
}
}
Ten krok jest niezbędny tylko wtedy, gdy Account.RegisterConfirmation
jest rusztowany. Niesfałdowany element RegisterConfirmation automatycznie wykrywa, kiedy element IEmailSender został zaimplementowany i zarejestrowany w kontenerze wstrzykiwania zależności.
Rejestrowanie, potwierdzanie wiadomości e-mail i resetowanie hasła
Uruchom aplikację internetową i przetestuj przepływ potwierdzenia konta i odzyskiwania hasła.
- Uruchamianie aplikacji i rejestrowanie nowego użytkownika
- Sprawdź adres e-mail, aby uzyskać link potwierdzenia konta. Jeśli nie otrzymasz wiadomości e-mail, zobacz Debugowanie wiadomości e-mail .
- Kliknij link, aby potwierdzić twoją wiadomość e-mail.
- Zaloguj się przy użyciu adresu e-mail i hasła.
- Wyloguj się.
Testowanie resetowania hasła
- W przypadku zalogowania wybierz pozycję Wyloguj.
- Wybierz link Zaloguj się i wybierz link Nie pamiętasz hasła?
- Wprowadź adres e-mail użyty do zarejestrowania konta.
- Zostanie wysłana wiadomość e-mail z linkiem umożliwiającym zresetowanie hasła. Sprawdź swój adres e-mail i kliknij link, aby zresetować hasło. Po pomyślnym zresetowaniu hasła możesz zalogować się przy użyciu poczty e-mail i nowego hasła.
Wyślij ponownie wiadomość e-mail z potwierdzeniem
Wybierz link Potwierdź ponownie wiadomość e-mail na stronie Logowanie.
Zmienianie limitu czasu wiadomości e-mail i działań
Domyślny limit czasu braku aktywności wynosi 14 dni. Poniższy kod ustawia limit czasu braku aktywności na 5 dni:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
builder.Services.ConfigureApplicationCookie(o => {
o.ExpireTimeSpan = TimeSpan.FromDays(5);
o.SlidingExpiration = true;
});
var app = builder.Build();
// Code removed for brevity
Zmienianie wszystkich cykli życia tokenu ochrony danych
Poniższy kod zmienia limit czasu wszystkich tokenów ochrony danych na 3 godziny:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
builder.Services.Configure<DataProtectionTokenProviderOptions>(o =>
o.TokenLifespan = TimeSpan.FromHours(3));
var app = builder.Build();
// Code removed for brevity.
Wbudowane Identity tokeny użytkownika (zobacz AspNetCore/src//IdentityExtensions.Core/src/TokenOptions.cs )mają jednorazowy limit czasu.
Zmienianie cyklu życia tokenu poczty e-mail
Domyślna żywotność tokenów Identity użytkownika wynosi jeden dzień. W tej sekcji pokazano, jak zmienić cykl życia tokenu poczty e-mail.
Dodaj niestandardowe DataProtectorTokenProvider<TUser> i DataProtectionTokenProviderOptions:
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);
}
}
Dodaj dostawcę niestandardowego do kontenera usługi:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
using WebPWrecover.TokenProviders;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
new TokenProviderDescriptor(
typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
}).AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
var app = builder.Build();
// Code removed for brevity.
Debugowanie wiadomości e-mail
Jeśli nie możesz uzyskać wiadomości e-mail, działa:
- Ustaw punkt przerwania w ,
EmailSender.Execute
aby zweryfikowaćSendGridClient.SendEmailAsync
, jest wywoływany. - Utwórz aplikację konsolową do wysyłania wiadomości e-mail przy użyciu kodu podobnego do
EmailSender.Execute
. - Przejrzyj stronę Działanie poczty e-mail.
- Sprawdź folder spamu.
- Wypróbuj inny alias poczty e-mail u innego dostawcy poczty e-mail (Microsoft, Yahoo, Gmail itp.)
- Spróbuj wysłać do różnych kont e-mail.
Najlepszym rozwiązaniem w zakresie zabezpieczeń jest brak używania wpisów tajnych produkcyjnych podczas testowania i programowania. Jeśli opublikujesz aplikację na platformie Azure, ustaw wpisy tajne usługi SendGrid jako ustawienia aplikacji w portalu aplikacji internetowej platformy Azure. System konfiguracji jest skonfigurowany do odczytu kluczy ze zmiennych środowiskowych.
Łączenie kont logowania społecznościowego i lokalnego
Aby ukończyć tę sekcję, musisz najpierw włączyć zewnętrznego dostawcę uwierzytelniania. Zobacz Uwierzytelnianie za pomocą usług Facebook, Google i zewnętrznego dostawcy.
Możesz połączyć konta lokalne i społecznościowe, klikając link e-mail. W poniższej sekwencji element "RickAndMSFT@gmail.com" jest najpierw tworzony jako identyfikator logowania lokalnego, ale najpierw możesz utworzyć konto jako identyfikator logowania społecznościowego, a następnie dodać nazwę logowania lokalnego.
Kliknij link Zarządzaj. Zwróć uwagę na 0 zewnętrznych (identyfikatorów logowania społecznościowego) skojarzonych z tym kontem.
Kliknij link do innej usługi logowania i zaakceptuj żądania aplikacji. Na poniższej ilustracji Facebook jest zewnętrznym dostawcą uwierzytelniania:
Te dwa konta zostały połączone. Możesz zalogować się przy użyciu dowolnego konta. Możesz chcieć, aby użytkownicy dodawali konta lokalne w przypadku, gdy usługa uwierzytelniania logowania społecznościowego nie działa lub prawdopodobnie utraciła dostęp do konta społecznościowego.
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 jako potwierdzonych.
- Potwierdź istniejących użytkowników. Na przykład wiadomości e-mail wysyłane wsadowo z linkami potwierdzenia.
Wymagania wstępne
Zestaw .NET Core 3.0 SDK lub nowszy
Tworzenie i testowanie aplikacji internetowej przy użyciu uwierzytelniania
Uruchom następujące polecenia, aby utworzyć aplikację internetową z uwierzytelnianiem.
dotnet new webapp -au Individual -uld -o WebPWrecover
cd WebPWrecover
dotnet run
Uruchom aplikację, wybierz link Zarejestruj i zarejestruj użytkownika. Po zarejestrowaniu /Identity/Account/RegisterConfirmation
nastąpi przekierowanie do strony zawierającej link do symulowania potwierdzenia wiadomości e-mail:
- Wybierz link
Click here to confirm your account
. - Wybierz link Zaloguj się i zaloguj się przy użyciu tych samych poświadczeń.
Hello YourEmail@provider.com!
Wybierz link, który przekierowuje Cię do/Identity/Account/Manage/PersonalData
strony.- Wybierz kartę Dane osobowe po lewej stronie, a następnie wybierz pozycję Usuń.
Konfigurowanie dostawcy poczty e-mail
W tym samouczku usługa SendGrid służy do wysyłania wiadomości e-mail. Możesz użyć innych dostawców poczty e-mail. Zalecamy wysyłanie wiadomości e-mail przy użyciu usługi SendGrid lub innej usługi poczty e-mail. Protokół SMTP jest trudny do skonfigurowania, więc poczta nie jest oznaczona jako spam.
Konto usługi SendGrid może wymagać dodania nadawcy.
Utwórz klasę, aby pobrać bezpieczny klucz poczty e-mail. W tym przykładzie utwórz polecenie Services/AuthMessageSenderOptions.cs
:
namespace WebPWrecover.Services;
public class AuthMessageSenderOptions
{
public string? SendGridKey { get; set; }
}
Konfigurowanie wpisów tajnych użytkownika usługi SendGrid
Ustaw element SendGridKey
za pomocą narzędzia secret-manager. Na przykład:
dotnet user-secrets set SendGridKey <SG.key>
Successfully saved SendGridKey = SG.keyVal to the secret store.
W systemie Windows menedżer wpisów tajnych przechowuje pary kluczy/wartości w secrets.json
pliku w %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId>
katalogu.
Zawartość secrets.json
pliku nie jest szyfrowana. Poniższy znacznik pokazuje secrets.json
plik. Wartość została usunięta SendGridKey
.
{
"SendGridKey": "<key removed>"
}
Aby uzyskać więcej informacji, zobacz Wzorzec i konfiguracja opcji.
Instalowanie usługi SendGrid
W tym samouczku pokazano, jak dodawać powiadomienia e-mail za pomocą usługi SendGrid, ale możesz wysyłać wiadomości e-mail przy użyciu protokołu SMTP i innych mechanizmów.
SendGrid
Zainstaluj pakiet NuGet:
W konsoli Menedżer pakietów wprowadź następujące polecenie:
Install-Package SendGrid
Zobacz Wprowadzenie do usługi SendGrid bezpłatnie , aby zarejestrować się w celu uzyskania bezpłatnego konta usługi SendGrid.
Implementowanie usługi IEmailSender
Aby zaimplementować IEmailSender
metodę , utwórz Services/EmailSender.cs
za pomocą kodu podobnego do następującego:
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
namespace WebPWrecover.Services;
public class EmailSender : IEmailSender
{
private readonly ILogger _logger;
public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
ILogger<EmailSender> logger)
{
Options = optionsAccessor.Value;
_logger = logger;
}
public AuthMessageSenderOptions Options { get; } //Set with Secret Manager.
public async Task SendEmailAsync(string toEmail, string subject, string message)
{
if (string.IsNullOrEmpty(Options.SendGridKey))
{
throw new Exception("Null SendGridKey");
}
await Execute(Options.SendGridKey, subject, message, toEmail);
}
public async Task Execute(string apiKey, string subject, string message, string toEmail)
{
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage()
{
From = new EmailAddress("Joe@contoso.com", "Password Recovery"),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(toEmail));
// Disable click tracking.
// See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
var response = await client.SendEmailAsync(msg);
_logger.LogInformation(response.IsSuccessStatusCode
? $"Email to {toEmail} queued successfully!"
: $"Failure Email to {toEmail}");
}
}
Konfigurowanie uruchamiania w celu obsługi poczty e-mail
Dodaj następujący kod do ConfigureServices
metody w Startup.cs
pliku :
- Dodaj
EmailSender
jako usługę przejściową. AuthMessageSenderOptions
Zarejestruj wystąpienie konfiguracji.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using WebPWrecover.Data;
using WebPWrecover.Services;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Rejestrowanie szkieletuKonfirmacja
Postępuj zgodnie z instrukcjami dotyczącymi tworzenia szkieletów Identity i szkieletów Account\RegisterConfirmation
.
Wyłącz domyślną weryfikację konta, gdy element Account.RegisterConfirmation został utworzony szkieletem
Ta sekcja ma zastosowanie tylko w przypadku Account.RegisterConfirmation
tworzenia szkieletów. Pomiń tę sekcję, jeśli nie utworzono szkieletu Account.RegisterConfirmation
.
Użytkownik jest przekierowywany do Account.RegisterConfirmation
lokalizacji, w której może wybrać link, aby potwierdzić konto. Wartość domyślna Account.RegisterConfirmation
jest używana tylko do testowania, automatyczna weryfikacja konta powinna być wyłączona w aplikacji produkcyjnej.
Aby wymagać potwierdzonego konta i uniemożliwić natychmiastowe logowanie podczas rejestracji, ustaw DisplayConfirmAccountLink = false
w pliku szkieletowym /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#nullable disable
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;
namespace WebPWrecover.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IEmailSender _sender;
public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
{
_userManager = userManager;
_sender = sender;
}
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string Email { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public bool DisplayConfirmAccountLink { get; set; }
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
returnUrl = returnUrl ?? Url.Content("~/");
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
return NotFound($"Unable to load user with email '{email}'.");
}
Email = email;
// Once you add a real email sender, you should remove this code that lets you confirm the account
DisplayConfirmAccountLink = false;
if (DisplayConfirmAccountLink)
{
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
EmailConfirmationUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
}
return Page();
}
}
}
Ten krok jest niezbędny tylko wtedy, gdy Account.RegisterConfirmation
jest rusztowany. Niesfałdowany element RegisterConfirmation automatycznie wykrywa, kiedy element IEmailSender został zaimplementowany i zarejestrowany w kontenerze wstrzykiwania zależności.
Rejestrowanie, potwierdzanie wiadomości e-mail i resetowanie hasła
Uruchom aplikację internetową i przetestuj przepływ potwierdzenia konta i odzyskiwania hasła.
- Uruchamianie aplikacji i rejestrowanie nowego użytkownika
- Sprawdź adres e-mail, aby uzyskać link potwierdzenia konta. Jeśli nie otrzymasz wiadomości e-mail, zobacz Debugowanie wiadomości e-mail .
- Kliknij link, aby potwierdzić twoją wiadomość e-mail.
- Zaloguj się przy użyciu adresu e-mail i hasła.
- Wyloguj się.
Testowanie resetowania hasła
- W przypadku zalogowania wybierz pozycję Wyloguj.
- Wybierz link Zaloguj się i wybierz link Nie pamiętasz hasła?
- Wprowadź adres e-mail użyty do zarejestrowania konta.
- Zostanie wysłana wiadomość e-mail z linkiem umożliwiającym zresetowanie hasła. Sprawdź swój adres e-mail i kliknij link, aby zresetować hasło. Po pomyślnym zresetowaniu hasła możesz zalogować się przy użyciu poczty e-mail i nowego hasła.
Wyślij ponownie wiadomość e-mail z potwierdzeniem
W programie ASP.NET Core 5.0 lub nowszym wybierz link Potwierdź ponownie wiadomość e-mail na stronie Logowanie .
Zmienianie limitu czasu wiadomości e-mail i działań
Domyślny limit czasu braku aktywności wynosi 14 dni. Poniższy kod ustawia limit czasu braku aktywności na 5 dni:
services.ConfigureApplicationCookie(o => {
o.ExpireTimeSpan = TimeSpan.FromDays(5);
o.SlidingExpiration = true;
});
Zmienianie wszystkich cykli życia tokenu ochrony danych
Poniższy kod zmienia limit czasu wszystkich tokenów ochrony danych na 3 godziny:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(
options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.Configure<DataProtectionTokenProviderOptions>(o =>
o.TokenLifespan = TimeSpan.FromHours(3));
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages();
}
Wbudowane Identity tokeny użytkownika (zobacz AspNetCore/src//IdentityExtensions.Core/src/TokenOptions.cs )mają jednorazowy limit czasu.
Zmienianie cyklu życia tokenu poczty e-mail
Domyślna żywotność tokenów Identity użytkownika wynosi jeden dzień. W tej sekcji pokazano, jak zmienić cykl życia tokenu poczty e-mail.
Dodaj niestandardowe DataProtectorTokenProvider<TUser> i DataProtectionTokenProviderOptions:
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);
}
}
Dodaj dostawcę niestandardowego do kontenera usługi:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(config =>
{
config.SignIn.RequireConfirmedEmail = true;
config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
new TokenProviderDescriptor(
typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
}).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddRazorPages();
}
Debugowanie wiadomości e-mail
Jeśli nie możesz uzyskać wiadomości e-mail, działa:
- Ustaw punkt przerwania w ,
EmailSender.Execute
aby zweryfikowaćSendGridClient.SendEmailAsync
, jest wywoływany. - Utwórz aplikację konsolową do wysyłania wiadomości e-mail przy użyciu kodu podobnego do
EmailSender.Execute
. - Przejrzyj stronę Działanie poczty e-mail.
- Sprawdź folder spamu.
- Wypróbuj inny alias poczty e-mail u innego dostawcy poczty e-mail (Microsoft, Yahoo, Gmail itp.)
- Spróbuj wysłać do różnych kont e-mail.
Najlepszym rozwiązaniem w zakresie zabezpieczeń jest brak używania wpisów tajnych produkcyjnych podczas testowania i programowania. Jeśli opublikujesz aplikację na platformie Azure, ustaw wpisy tajne usługi SendGrid jako ustawienia aplikacji w portalu aplikacji internetowej platformy Azure. System konfiguracji jest skonfigurowany do odczytu kluczy ze zmiennych środowiskowych.
Łączenie kont logowania społecznościowego i lokalnego
Aby ukończyć tę sekcję, musisz najpierw włączyć zewnętrznego dostawcę uwierzytelniania. Zobacz Uwierzytelnianie za pomocą usług Facebook, Google i zewnętrznego dostawcy.
Możesz połączyć konta lokalne i społecznościowe, klikając link e-mail. W poniższej sekwencji element "RickAndMSFT@gmail.com" jest najpierw tworzony jako identyfikator logowania lokalnego, ale najpierw możesz utworzyć konto jako identyfikator logowania społecznościowego, a następnie dodać nazwę logowania lokalnego.
Kliknij link Zarządzaj. Zwróć uwagę na 0 zewnętrznych (identyfikatorów logowania społecznościowego) skojarzonych z tym kontem.
Kliknij link do innej usługi logowania i zaakceptuj żądania aplikacji. Na poniższej ilustracji Facebook jest zewnętrznym dostawcą uwierzytelniania:
Te dwa konta zostały połączone. Możesz zalogować się przy użyciu dowolnego konta. Możesz chcieć, aby użytkownicy dodawali konta lokalne w przypadku, gdy usługa uwierzytelniania logowania społecznościowego nie działa lub prawdopodobnie utraciła dostęp do konta społecznościowego.
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 jako potwierdzonych.
- Potwierdź istniejących użytkowników. Na przykład wiadomości e-mail wysyłane wsadowo z linkami potwierdzenia.