Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Von Rick Anderson, Ponant und Joe Audette
In diesem Tutorial erfahren Sie, wie Sie eine ASP.NET Core-App mit E-Mail-Bestätigung und Kennwortzurücksetzung erstellen. Dieses Tutorial ist kein Artikel für Anfänger. Sie sollten mit den folgenden Punkten vertraut sein:
Blazor Anleitungen, die den Leitfaden in diesem Artikel hinzufügen oder ersetzen, finden Sie in den folgenden Ressourcen:
Voraussetzungen
- .NET 6 oder höher SDK
- Erfolgreiches Senden von E-Mails aus einer C#-Konsolen-App mithilfe der SendGrid-API (Twilio)
Erstellen und Testen einer Web-App mit Authentifizierung
Führen Sie die folgenden Befehle aus, um eine Web-App mit Authentifizierung zu erstellen:
dotnet new webapp -au Individual -o WebPWrecover
cd WebPWrecover
dotnet run
Registrieren eines Benutzers mit simulierter E-Mail-Bestätigung
Führen Sie die App aus, wählen Sie den Link Registrieren aus, und registrieren Sie eine*n Benutzer*in.
Nach Abschluss der /Identity/Account/RegisterConfirmation Registrierung werden Sie zur Seite umgeleitet, die einen Link zum Simulieren der E-Mail-Bestätigung enthält.
Wählen Sie den Link
Click here to confirm your accountaus.Wählen Sie den Link Login (Anmelden) aus, und melden Sie sich mit denselben Anmeldeinformationen an.
Wählen Sie den Link
Hello YourEmail@provider.com!aus, der eine Weiterleitung zur Seite/Identity/Account/Manage/PersonalDatadurchführt.Wählen Sie die Registerkarte " Persönliche Daten " und dann "Löschen" aus.
Der Click here to confirm your account Link wird angezeigt, da die IEmailSender-Schnittstelle noch nicht implementiert und beim Container zum Einfügen von Abhängigkeiten registriert ist. Weitere Informationen finden Sie in der RegisterConfirmation-Quelle.
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)).
Konfigurieren eines E-Mail-Anbieters
In diesem Lernprogramm wird Twilio SendGrid zum Senden von E-Mails verwendet. Zum Senden von E-Mails sind ein SendGrid-Konto und ein Schlüssel erforderlich. Es wird empfohlen, SendGrid oder einen anderen E-Mail-Dienst anstelle von SMTP zu verwenden, um E-Mails zu senden. Es ist schwierig, SMTP richtig zu schützen und einzurichten.
Das SendGrid-Konto erfordert möglicherweise das Hinzufügen eines Absenders.
Erstellen Sie eine Klasse, um den sicheren E-Mail-Schlüssel abzurufen. Erstellen Sie für dieses Beispiel die Datei "Dienste/AuthMessageSenderOptions.cs ":
namespace WebPWrecover.Services;
public class AuthMessageSenderOptions
{
public string? SendGridKey { get; set; }
}
Konfigurieren von SendGrid-Benutzergeheimnissen
Legen Sie den SendGridKey Wert mit dem Tool für geheimen Manager fest. Beispiel:
dotnet user-secrets set SendGridKey <key>
Successfully saved SendGridKey to the secret store.
In Windows speichert der geheime Manager Schlüssel-Wert-Paare in einer Datei secrets.json im Verzeichnis %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId>.
Der Inhalt der secrets.json Datei ist nicht verschlüsselt. Das folgende Markup zeigt die secrets.json Datei. Der SendGridKey Wert wird aus dem Beispiel entfernt.
{
"SendGridKey": "<key removed>"
}
Weitere Informationen finden Sie im Muster Options und Configuration in ASP.NET Core.
Installieren von SendGrid
In diesem Tutorial wird gezeigt, wie Sie E-Mail-Benachrichtigungen über SendGrid hinzufügen. Es können aber auch andere E-Mail-Anbieter verwendet werden.
Installieren Sie das NuGet-Paket SendGrid:
Geben Sie in der Paket-Manager-Konsole den folgenden Befehl ein:
Install-Package SendGrid
Um sich für ein kostenloses SendGrid-Konto zu registrieren, beginnen Sie mit dem Senden mit einer kostenlosen SendGrid-E-Mail-API-Testversion.
Implementieren von IEmailSender
Um die Schnittstelle zu implementieren, erstellen Sie die IEmailSenderDatei "Services/EmailSender.cs " mit Code, der dem folgenden Beispiel ähnelt:
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}");
}
}
Konfigurieren der App zur Unterstützung von E-Mails
Fügen Sie der datei Program.cs den folgenden Code hinzu, der die folgenden Aufgaben ausführt:
- Fügt die
EmailSenderInstanz als vorübergehenden Dienst hinzu. - Registriert die
AuthMessageSenderOptionsKonfigurationsinstanz.
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();
Standardmäßige Kontobestätigung deaktivieren, wenn Account.RegisterConfirmation per Scaffolding generiert wird
Wenn Account.RegisterConfirmation ein Gerüst erstellt wird, führen Sie die Anweisungen in diesem Abschnitt aus.
Important
Wenn Account.RegisterConfirmationkein Gerüst erstellt wurde, überspringen Sie die folgenden Anweisungen, und fahren Sie mit dem nächsten Abschnitt fort.
Der Benutzer wird auf die /Identity/Account/RegisterConfirmationSeite umgeleitet, auf der er einen Link auswählen kann, mit dem das Konto bestätigt werden kann. Der Standardwert Account.RegisterConfirmation wird nur für Tests verwendet. Die automatische Kontoüberprüfung sollte in einer Produktions-App deaktiviert werden.
Um ein bestätigtes Konto zu verlangen und die unmittelbare Anmeldung bei der Registrierung zu verhindern, setzen Sie DisplayConfirmAccountLink = false in der generierten Datei /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs fest:
// 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();
}
}
}
Dieser Schritt ist nur erforderlich, wenn Account.RegisterConfirmation per Scaffolding generiert wird.
Das nicht gerüstete RegisterConfirmation erkennt automatisch, wenn ein IEmailSender implementiert und beim Abhängigkeitseinfügungscontainer registriert wird.
Registrieren, Bestätigen per E-Mail und Zurücksetzen des Kennworts
Starten Sie die Web-App, und testen Sie den Ablauf zur Kontobestätigung und Kennwortwiederherstellung.
Führen Sie die App aus, und registrieren Sie einen neuen Benutzer.
Überprüfen Sie Ihre E-Mail auf einen Link zur Kontobestätigung. Wenn Sie die E-Mail nicht erhalten, lesen Sie den Abschnitt " Debug-E-Mail " zur Problembehandlung.
Wählen Sie den Link aus, und bestätigen Sie Ihre E-Mail.
Melden Sie sich mit Ihrer E-Mail-Adresse und Ihrem Kennwort an.
Melden Sie sich ab.
Passwortzurücksetzung testen
Wenn Sie angemeldet sind, wählen Sie Logout (Abmelden) aus.
Wählen Sie den Link "Anmelden" und dann den Link " Kennwort vergessen" aus.
Geben Sie die E-Mail-Adresse ein, die Sie zum Registrieren des Kontos verwendet haben. Die App sendet eine E-Mail mit einem Link, um Ihr Kennwort zurückzusetzen.
Wechseln Sie zur gesendeten E-Mail-Nachricht.
Wählen Sie den Link aus, und setzen Sie Ihr Kennwort zurück.
Nachdem Ihr Kennwort erfolgreich zurückgesetzt wurde, können Sie sich mit Ihrer E-Mail und ihrem neuen Kennwort anmelden.
Erneutes Senden von E-Mail-Bestätigungen
In diesem Abschnitt wird der Code beschrieben, der den E-Mail-Bestätigungsprozess und zugehörige Aufgaben unterstützt.
- Wählen Sie zunächst auf der Anmeldeseite den Link "E-Mail-Bestätigung erneut senden" aus.
E-Mail- und Aktivitäts-Timeout ändern
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 fest:
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
Ändern der Lebensdauer aller Datenschutztoken
Der folgende Code ändert den Timeoutzeitraum für alle Datenschutztoken auf drei Stunden:
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.
Die integrierten Identity Benutzertoken (siehe AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs Source) verfügen über ein eintägiges Timeout.
Ändern der Lebensdauer von E-Mail-Token
Die Standardlebensdauer von Identity-Benutzertoken beträgt einen Tag.
Der folgende Code zeigt, wie Die Lebensdauer des E-Mail-Tokens geändert wird.
Fügen Sie eine benutzerdefinierte DataProtectorTokenProvider<TUser> Klasse und DataProtectionTokenProviderOptions Klasse hinzu:
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);
}
}
Fügen Sie dem Dienstcontainer den benutzerdefinierten Anbieter hinzu:
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.
Debuggen von E-Mails
Wenn der E-Mail-Prozess nicht wie erwartet funktioniert, probieren Sie die folgenden Schritte zur Problembehandlung aus:
Legen Sie einen Haltepunkt in der
EmailSender.ExecuteMethode fest, und überprüfen Sie, ob dieSendGridClient.SendEmailAsyncMethode aufgerufen wird.Erstellen Sie eine Konsolen-App, um E-Mails mithilfe eines ähnlichen Codes zu senden.
EmailSender.ExecuteÜberprüfen Sie die Seite mit E-Mail-Aktivitäten.
Überprüfen Sie Ihren Spamordner.
Probieren Sie einen anderen E-Mail-Alias für einen anderen E-Mail-Anbieter aus, z. B. Microsoft, Yahoo, Gmail usw.
Versuchen Sie, die E-Mail an andere E-Mail-Konten zu senden.
Tipp
Eine bewährte Sicherheitsmethode besteht darin, keine Produktionsgeheimnisse bei Tests und der Entwicklung zu verwenden. Wenn Sie die App in Azure veröffentlichen, legen Sie die SendGrid-Geheimnisse im Azure-Web-App-Portal als Anwendungseinstellungen fest. Das Konfigurationssystem ist zum Lesen von Schlüsseln aus Umgebungsvariablen eingerichtet.
Kombinieren von Konten bei sozialen Medien und lokalen Anmeldekonten
Um diesen Abschnitt abzuschließen, müssen Sie zunächst einen externen Authentifizierungsanbieter aktivieren. Weitere Informationen finden Sie unter Verwenden von externen Anmeldeanbietern mit Identity in ASP.NET Core.
In dieser Sequenz wird die E-Mail-Adresse RickAndMSFT@gmail.com zuerst als lokale Anmeldung erstellt. Sie können das Konto jedoch zuerst als anmeldung für soziale Netzwerke erstellen und dann eine lokale Anmeldung hinzufügen.
Um lokale und soziale Konten zu kombinieren, wählen Sie den Link "E-Mail-Adresse" aus.
Wählen Sie auf der Seite "Konto verwalten " den Link "Verwalten" aus.
Beachten Sie, dass dem authentifizierten Konto derzeit null (0) externe (soziale Anmeldungen) zugeordnet sind.
Wählen Sie auf der Seite "Externe Anmeldungen verwalten " den Link zu einem anderen Anmeldedienst aus. Folgen Sie den Dienstaufforderungen, und akzeptieren Sie die App-Anforderungen.
In der folgenden Abbildung wird Facebook als externer Authentifizierungsanbieter hinzugefügt:
Die Authentifizierung für die E-Mail-Adresse des Benutzers kombiniert jetzt lokale und externe Konten (soziale Netzwerke). Der Benutzer kann sich mit beiden Konten anmelden.
Tipp
Es empfiehlt sich, Ihren Benutzern zu empfehlen, Ihrer App ein lokales Konto hinzuzufügen. Dieser Ansatz kann dazu beitragen, den fortgesetzten Zugriff sicherzustellen, falls der Authentifizierungsdienst für soziale Netzwerke deaktiviert ist, oder er verliert den Zugriff auf sein soziales Konto.
Aktivieren der Kontobestätigung, nachdem eine Website Benutzer*innen enthält
Wenn Sie die Kontobestätigung auf einer Website mit vorhandenen Benutzern aktivieren, sperren Sie sie, da ihre Konten nicht bestätigt werden.
Um das Problem der vorhandenen Benutzersperre zu umgehen, verwenden Sie einen der folgenden Ansätze:
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.
Voraussetzungen
Erstellen und Testen einer Web-App mit Authentifizierung
Führen Sie die folgenden Befehle aus, um eine Web-App mit Authentifizierung zu erstellen.
dotnet new webapp -au Individual -uld -o WebPWrecover
cd WebPWrecover
dotnet run
Führen Sie die App aus, wählen Sie den Link Registrieren aus, und registrieren Sie eine*n Benutzer*in. Nach der Registrierung werden Sie zur /Identity/Account/RegisterConfirmation-Seite weitergeleitet, die einen Link zum Simulieren der E-Mail-Bestätigung enthält:
- Wählen Sie den Link
Click here to confirm your accountaus. - Wählen Sie den Link Login (Anmelden) aus, und melden Sie sich mit denselben Anmeldeinformationen an.
- Wählen Sie den Link
Hello YourEmail@provider.com!aus, der eine Weiterleitung zur Seite/Identity/Account/Manage/PersonalDatadurchführt. - Wählen Sie links die Registerkarte Personal data (Persönliche Daten) und dann Delete (Löschen) aus.
Konfigurieren eines E-Mail-Anbieters
In diesem Tutorial wird zum Senden von E-Mails SendGrid verwendet. Sie können andere E-Mail-Anbieter verwenden. Es wird empfohlen, zum Senden von E-Mails SendGrid oder einen anderen E-Mail-Dienst zu verwenden. SMTP ist schwierig zu konfigurieren, damit E-Mails nicht als Spam gekennzeichnet werden.
Das SendGrid-Konto erfordert möglicherweise das Hinzufügen eines Absenders.
Erstellen Sie eine Klasse, um den sicheren E-Mail-Schlüssel abzurufen. Erstellen Sie für dieses Beispiel Services/AuthMessageSenderOptions.cs:
namespace WebPWrecover.Services;
public class AuthMessageSenderOptions
{
public string? SendGridKey { get; set; }
}
Konfigurieren von SendGrid-Benutzergeheimnissen
Legen Sie SendGridKey mit dem Tool secret-manager fest. Beispiel:
dotnet user-secrets set SendGridKey <SG.key>
Successfully saved SendGridKey = SG.keyVal to the secret store.
Unter Windows speichert der Geheimnis-Manager Schlüssel-Wert-Paare in einer Datei secrets.json im Verzeichnis %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId>.
Der Inhalt der Datei secrets.json wird nicht verschlüsselt. Das folgende Markup zeigt die Datei secrets.json. Der SendGridKey-Wert wurde entfernt.
{
"SendGridKey": "<key removed>"
}
Weitere Informationen finden Sie unter Optionsmuster und Konfiguration.
Installieren von SendGrid
In diesem Tutorial erfahren Sie, wie Sie E-Mail-Benachrichtigungen über SendGrid hinzufügen. Sie können E-Mails aber auch mithilfe von SMTP und anderen Mechanismen senden.
Installieren Sie das NuGet-Paket SendGrid:
Geben Sie in der Paket-Manager-Konsole den folgenden Befehl ein:
Install-Package SendGrid
Informationen zur Registrierung eines kostenlosen SendGrid-Kontos finden Sie unter Get Started with SendGrid for Free (Erste Schritte mit dem kostenlosen SendGrid).
Implementieren von IEmailSender
Um IEmailSender zu implementieren, erstellen Sie Services/EmailSender.cs mit Code ähnlich dem folgenden:
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}");
}
}
Konfigurieren des Starts zur Unterstützung von E-Mails
Fügen Sie der ConfigureServices-Methode in der Datei Startup.cs den folgenden Code hinzu:
- Fügen Sie
EmailSenderals vorübergehenden Dienst hinzu. - Registrieren Sie die
AuthMessageSenderOptions-Konfigurationsinstanz.
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();
Gerüst für RegisterConfirmation erstellen
Befolgen Sie die Anweisungen für Gerüst Identity und Gerüst Account\RegisterConfirmation.
Standardmäßige Kontobestätigung deaktivieren, wenn Account.RegisterConfirmation per Scaffolding generiert wird
Wenn Account.RegisterConfirmation ein Gerüst erstellt wird, führen Sie die Anweisungen in diesem Abschnitt aus.
Important
Wenn Account.RegisterConfirmationkein Gerüst erstellt wurde, überspringen Sie die folgenden Anweisungen, und fahren Sie mit dem nächsten Abschnitt fort.
Der Benutzer wird auf die /Identity/Account/RegisterConfirmationSeite umgeleitet, auf der er einen Link auswählen kann, mit dem das Konto bestätigt werden kann. Der Standardwert Account.RegisterConfirmation wird nur für Tests verwendet. Die automatische Kontoüberprüfung sollte in einer Produktions-App deaktiviert werden.
Um ein bestätigtes Konto zu verlangen und die unmittelbare Anmeldung bei der Registrierung zu verhindern, setzen Sie DisplayConfirmAccountLink = false in der generierten Datei /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs fest:
// 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();
}
}
}
Dieser Schritt ist nur erforderlich, wenn Account.RegisterConfirmation per Scaffolding generiert wird.
Das nicht gerüstete RegisterConfirmation erkennt automatisch, wenn ein IEmailSender implementiert und beim Abhängigkeitseinfügungscontainer registriert wird.
Registrieren, Bestätigen per E-Mail und Zurücksetzen des Kennworts
Starten Sie die Web-App, und testen Sie den Ablauf zur Kontobestätigung und Kennwortwiederherstellung.
- Ausführen der App und Registrieren eine*r neue*n Benutzer*in
- Überprüfen Sie Ihre E-Mail auf einen Link zur Kontobestätigung. Wenn Sie die E-Mail nicht erhalten haben, finden Sie unter Debuggen von E-Mails weitere Informationen.
- Wählen Sie den Link aus, um Ihre E-Mail-Adresse zu bestätigen.
- Melden Sie sich mit Ihrer E-Mail-Adresse und Ihrem Kennwort an.
- Melden Sie sich ab.
Passwortzurücksetzung testen
- Wenn Sie angemeldet sind, wählen Sie Logout (Abmelden) aus.
- Wählen Sie den Link Log in (Anmelden) und dann den Link Forgot your password? (Kennwort vergessen?) aus.
- Geben Sie die E-Mail-Adresse ein, die Sie zum Registrieren des Kontos verwendet haben.
- Es wird eine E-Mail mit einem Link zum Zurücksetzen Ihres Kennworts gesendet. Überprüfen Sie Ihre E-Mails, und wählen Sie den Link aus, um Ihr Kennwort zurückzusetzen. Nachdem Ihr Kennwort erfolgreich zurückgesetzt wurde, können Sie sich mit Ihrer E-Mail-Adresse und dem neuen Kennwort anmelden.
Erneutes Senden von E-Mail-Bestätigungen
Wählen Sie in .NET 5 oder höher auf der Anmeldeseite den Link "E-Mail-Bestätigung erneut senden" aus.
E-Mail- und Aktivitäts-Timeout ändern
Der Standardzeitraum für die Inaktivität bis zum Timeout beträgt 14 Tage. Der folgende Code legt das Inaktivitätstimeout auf 5 Tage fest:
services.ConfigureApplicationCookie(o => {
o.ExpireTimeSpan = TimeSpan.FromDays(5);
o.SlidingExpiration = true;
});
Ändern der Lebensdauer aller Datenschutztoken
Der folgende Code ändert den Timeoutzeitraum für alle Datenschutztoken auf 3 Stunden:
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();
}
Die integrierten Identity-Benutzertoken (siehe AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs) weisen ein Timeout von einem Tag auf.
Ändern der Lebensdauer von E-Mail-Token
Die Standardlebensdauer von Identity-Benutzertoken beträgt einen Tag. In diesem Abschnitt wird gezeigt, wie Sie die Lebensdauer von E-Mail-Token ändern.
Fügen Sie benutzerdefinierte DataProtectorTokenProvider<TUser> und DataProtectionTokenProviderOptions hinzu:
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);
}
}
Fügen Sie dem Dienstcontainer den benutzerdefinierten Anbieter hinzu:
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();
}
Debuggen von E-Mails
Wenn E-Mails nicht funktionieren:
- Legen Sie einen Breakpoint in
EmailSender.Executefest, um zu überprüfen, obSendGridClient.SendEmailAsyncaufgerufen wird. - Erstellen Sie eine Konsolen-App zum Senden von E-Mails mit ähnlichem Code wie
EmailSender.Execute. - Überprüfen Sie die Seite mit E-Mail-Aktivitäten.
- Überprüfen Sie Ihren Spamordner.
- Versuchen Sie es mit einem anderen E-Mail-Alias bei einem anderen E-Mail-Anbieter (Microsoft, Yahoo, Gmail usw.).
- Versuchen Sie, die E-Mail an andere E-Mail-Konten zu senden.
Eine bewährte Sicherheitsmethode besteht darin, keine Produktionsgeheimnisse bei Tests und der Entwicklung zu verwenden. Wenn Sie die App in Azure veröffentlichen, legen Sie die SendGrid-Geheimnisse im Azure-Web-App-Portal als Anwendungseinstellungen fest. Das Konfigurationssystem ist zum Lesen von Schlüsseln aus Umgebungsvariablen eingerichtet.
Kombinieren von Konten bei sozialen Medien und lokalen Anmeldekonten
Um diesen Abschnitt abzuschließen, müssen Sie zunächst einen externen Authentifizierungsanbieter aktivieren. Weitere Informationen finden Sie unter Authentifizierung über Facebook, Google und externe Anbieter.
Sie können lokale Konten und Konten bei sozialen Medien kombinieren, indem Sie Ihren E-Mail-Link auswählen. In der folgenden Sequenz wird „RickAndMSFT@gmail.com“ zuerst als lokaler Anmeldename erstellt. Sie können das Konto jedoch zuerst als Anmeldung für soziale Netzwerke erstellen und dann eine lokale Anmeldung hinzufügen.
Wählen Sie den Link Verwalten aus. Beachten Sie, dass diesem Konto 0 (null) externe Konten (bei sozialen Medien) zugeordnet sind.
Wählen Sie den Link zu einem anderen Anmeldedienst aus, und akzeptieren Sie die App-Anforderungen. In der folgenden Abbildung ist der externe Authentifizierungsanbieter Facebook:
Die beiden Konten wurden kombiniert. Sie können sich mit beiden Konten anmelden. Möglicherweise möchten Sie, dass Ihre Benutzer*innen lokale Konten hinzufügen, falls ihr Authentifizierungsdienst beim sozialen Netzwerk ausfällt oder wahrscheinlicher, falls sie den Zugriff auf ihr Konto beim sozialen Netzwerk verloren haben.
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.