Confirmation de compte et récupération de mot de passe dans ASP.NET Core Blazor
Cet article explique comment configurer une application web ASP.NET Core Blazor avec confirmation par e-mail et réinitialisation de mot de passe.
Espace de noms
L’espace de noms de l’application utilisé par l’exemple de cet article est BlazorSample
. Mettez à jour les exemples de code pour utiliser l’espace de noms de votre application.
Sélectionner et configurer un fournisseur de messagerie électronique
Dans cet article, l’API transactionnelle de Mailchimp est utilisée via Mandrill.net pour envoyer un e-mail. Nous vous recommandons d’utiliser un service de messagerie pour envoyer des e-mails plutôt que SMTP. SMTP est difficile à configurer et à sécuriser correctement. Quel que soit le service de messagerie que vous utilisez, accédez à leurs conseils pour les applications .NET, créez un compte, configurez une clé API pour leur service et installez les packages NuGet requis.
Créez une classe pour récupérer (fetch) la clé API de messagerie sécurisée. L’exemple de cet article utilise une classe nommée AuthMessageSenderOptions
avec une propriété EmailAuthKey
pour contenir la clé.
AuthMessageSenderOptions
:
namespace BlazorSample;
public class AuthMessageSenderOptions
{
public string? EmailAuthKey { get; set; }
}
Enregistrer l’instance de configuration AuthMessageSenderOptions
dans le fichier Program
:
builder.Services.Configure<AuthMessageSenderOptions>(builder.Configuration);
Configurer un secret utilisateur pour la clé de sécurité du fournisseur
Définissez la clé avec l’outil secret-manager. Dans l’exemple suivant, le nom de la clé est EmailAuthKey
et la clé est représentée par l’espace réservé {KEY}
. Dans un interpréteur de commandes, accédez au dossier racine de l’application et exécutez la commande suivante avec la clé API :
dotnet user-secrets set "EmailAuthKey" "{KEY}"
Pour plus d’informations, consultez Stockage sécurisé des secrets d’application dans le développement en ASP.NET Core.
Implémentez IEmailSender
Implémentez IEmailSender
pour le fournisseur. L’exemple suivant est basé sur l’API transactionnelle de Mailchimp à l’aide de Mandrill.net. Pour un autre fournisseur, reportez-vous à leur documentation sur la façon d’implémenter l’envoi d’un message dans la méthode 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);
}
}
Remarque
Le contenu du corps des messages peut nécessiter un encodage spécial pour le fournisseur du service de messagerie. Si certains liens dans le corps du message ne fonctionnent pas, consultez la documentation du fournisseur de services.
Configurer l’application pour prendre en charge les e-mails
Dans le fichier Program
, remplacez l’implémentation de l’expéditeur d’e-mail par EmailSender
:
- builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
+ builder.Services.AddSingleton<IEmailSender<ApplicationUser>, EmailSender>();
Supprimez le IdentityNoOpEmailSender
(Components/Account/IdentityNoOpEmailSender.cs
) de l’application.
Dans le composant RegisterConfirmation
(Components/Account/Pages/RegisterConfirmation.razor
), supprimez le bloc conditionnel dans le bloc @code
qui vérifie si EmailSender
est IdentityNoOpEmailSender
:
- else if (EmailSender is IdentityNoOpEmailSender)
- {
- ...
- }
En outre, dans le composant RegisterConfirmation
, supprimez le balisage Razor et le code pour vérifier le champ emailConfirmationLink
, en laissant uniquement la ligne demandant à l’utilisateur de vérifier son e-mail ...
- @if (emailConfirmationLink is not null)
- {
- ...
- }
- else
- {
<p>Please check your email to confirm your account.</p>
- }
@code {
- private string? emailConfirmationLink;
...
}
E-mail et délai d’expiration d’activité
Le délai d'inactivité par défaut est de 14 jours. Le code suivant définit le délai d’expiration d’activité à 5 jours avec une fenêtre d’expiration glissante :
builder.Services.ConfigureApplicationCookie(options => {
options.ExpireTimeSpan = TimeSpan.FromDays(5);
options.SlidingExpiration = true;
});
Modifier les durées de vie de tous les jetons de protection des données
Le code suivant modifie la période de délai d’expiration de tous les jetons de protection des données à 3 heures :
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
options.TokenLifespan = TimeSpan.FromHours(3));
Les jetons utilisateur Identity intégrés (AspNetCore/src/Identity/Extensions.Core/src/TokenOptions.cs) ont un délai d’expiration d’un jour.
Remarque
Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Modifier la durée de vie du jeton d’e-mail
La durée de vie par défaut des jetons utilisateur Identity est d’un jour.
Remarque
Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Pour modifier la durée de vie du jeton d’e-mail, ajoutez un DataProtectorTokenProvider<TUser> et DataProtectionTokenProviderOptions personnalisés :
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);
}
}
Configurer les services pour utiliser le fournisseur de jetons personnalisé dans le fichier Program
:
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>>();
Résolution des problèmes
Si vous ne parvenez pas à faire fonctionner les e-mails :
- Définissez un point d’arrêt dans
EmailSender.Execute
pour vérifier queSendEmailAsync
est appelé. - Créez une application console pour envoyer un e-mail à l’aide de code similaire à
EmailSender.Execute
pour déboguer le problème. - Passez en revue les pages d’historique des e-mails du compte sur le site web du fournisseur de messagerie.
- Vérifiez les messages dans votre dossier de courrier indésirable.
- Essayez un autre alias de messagerie sur un autre fournisseur de messagerie, tel que Microsoft, Yahoo, ou Gmail.
- Essayez de faire un envoi à d’autres comptes de messagerie.
Avertissement
N’utilisez pas de secrets de production dans le test et le développement. Si vous publiez l’application sur Azure, définissez les secrets comme paramètres d’application dans le portail d’application web Azure. Le système de configuration est configuré pour lire les clés des variables d'environnement.
Activer la confirmation de compte après qu’un site a des utilisateurs
L’activation de la confirmation de compte sur un site avec des utilisateurs bloque tous les utilisateurs existants. Les utilisateurs existants sont bloqués, car leurs comptes ne sont pas confirmés. Pour contourner un blocage utilisateur existant, utilisez l’une des approches suivantes :
- Mettez à jour la base de données pour marquer tous les utilisateurs existants comme étant confirmés.
- Confirmer les utilisateurs existants. Par exemple, envoyez des e-mails par lots avec des liens de confirmation.
Ressources supplémentaires
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour