Confirmation de compte et récupération de mot de passe dans ASP.NET Core Blazor
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Cet article explique comment configurer une Blazor Web App ASP.NET Core avec confirmation par e-mail et réinitialisation de mot de passe.
Remarque
Cet article s’applique uniquement à Blazor Web Apps. Pour implémenter la confirmation par e-mail et la récupération de mot de passe pour les applications autonomes Blazor WebAssembly avec ASP.NET Core Identity, consultez confirmation de compte et récupération de mot de passe dans ASP.NET Core Blazor WebAssembly avec ASP.NET Core Identity.
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 contenir la clé API du fournisseur de courrier secret. L’exemple de cet article utilise une classe nommée AuthMessageSenderOptions
avec une EmailAuthKey
propriété pour contenir la clé.
AuthMessageSenderOptions.cs
:
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
Si le projet a déjà été initialisé pour l’outil Gestionnaire de secrets, il aura déjà un identificateur de secrets d’application (<AppSecretsId>
) dans son fichier projet (.csproj
). Dans Visual Studio, vous pouvez savoir si l’ID des secrets d’application est présent en examinant le volet Propriétés lorsque le projet est sélectionné dans Explorateur de solutions. Si l’application n’a pas été initialisée, exécutez la commande suivante dans un interpréteur de commandes ouvert au répertoire du projet. Dans Visual Studio, vous pouvez utiliser l’invite de commandes Developer PowerShell.
dotnet user-secrets init
Définissez la clé API avec l’outil Gestionnaire de secrets. Dans l’exemple suivant, le nom de la clé doit EmailAuthKey
correspondre AuthMessageSenderOptions.EmailAuthKey
et la clé est représentée par l’espace {KEY}
réservé. Exécutez la commande suivante avec la clé API :
dotnet user-secrets set "EmailAuthKey" "{KEY}"
Si vous utilisez Visual Studio, vous pouvez confirmer que le secret est défini en cliquant avec le bouton droit sur le projet de serveur dans Explorateur de solutions et en sélectionnant Gérer les secrets utilisateur.
Pour plus d’informations, consultez Stockage sécurisé des secrets d’application dans le développement en ASP.NET Core.
Avertissement
Ne stockez pas les secrets d’application, les chaîne de connexion, les informations d’identification, les mots de passe, les numéros d’identification personnels (PIN), le code C#/.NET privé ou les clés/jetons privés dans le code côté client, qui est toujours non sécurisé. Dans les environnements de test/intermédiaire et de production, le code côté Blazor serveur et les API web doivent utiliser des flux d’authentification sécurisés qui évitent de conserver les informations d’identification dans le code du projet ou les fichiers de configuration. En dehors des tests de développement locaux, nous vous recommandons d’éviter l’utilisation de variables d’environnement pour stocker des données sensibles, car les variables d’environnement ne sont pas l’approche la plus sécurisée. Pour les tests de développement locaux, l’outil Secret Manager est recommandé pour sécuriser les données sensibles. Pour plus d’informations, consultez Gestion sécurisée des données sensibles et des informations d’identification.
Implémentez IEmailSender
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 électronique.
Ajoutez le package NuGet Mandrill.net au projet.
Ajoutez la classe suivante EmailSender
pour implémenter IEmailSender<TUser>. Dans l’exemple suivant, ApplicationUser
est un IdentityUser. Le balisage HTML du message peut être personnalisé. Tant que le message
caractère passé MandrillMessage
commence par le <
caractère, l’API Mandrill.net part du principe que le corps du message est composé en HTML.
Components/Account/EmailSender.cs
:
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Mandrill;
using Mandrill.Model;
using BlazorSample.Data;
namespace BlazorSample.Components.Account;
public class EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
ILogger<EmailSender> logger) : IEmailSender<ApplicationUser>
{
private readonly ILogger logger = logger;
public AuthMessageSenderOptions Options { get; } = optionsAccessor.Value;
public Task SendConfirmationLinkAsync(AppUser user, string email,
string confirmationLink) => SendEmailAsync(email, "Confirm your email",
"<html lang=\"en\"><head></head><body>Please confirm your account by " +
$"<a href='{confirmationLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetLinkAsync(AppUser user, string email,
string resetLink) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password by " +
$"<a href='{resetLink}'>clicking here</a>.</body></html>");
public Task SendPasswordResetCodeAsync(AppUser user, string email,
string resetCode) => SendEmailAsync(email, "Reset your password",
"<html lang=\"en\"><head></head><body>Please reset your password " +
$"using the following code:<br>{resetCode}</body></html>");
public async Task SendEmailAsync(string toEmail, string subject, string message)
{
if (string.IsNullOrEmpty(Options.EmailAuthKey))
{
throw new Exception("Null EmailAuthKey");
}
await Execute(Options.EmailAuthKey, subject, message, toEmail);
}
public async Task Execute(string apiKey, string subject, string message,
string toEmail)
{
var api = new MandrillApi(apiKey);
var mandrillMessage = new MandrillMessage("sarah@contoso.com", toEmail,
subject, message);
await api.Messages.SendAsync(mandrillMessage);
logger.LogInformation("Email to {EmailAddress} sent!", toEmail);
}
}
Remarque
Le contenu du corps des messages peut nécessiter un encodage spécial pour le fournisseur du service de messagerie. Si des liens dans le corps du message ne peuvent pas être suivis dans le message électronique, consultez la documentation du fournisseur de services pour résoudre le problème.
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;
...
}
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.
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’inactivité à cinq 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 ASP.NET Core
Le code suivant modifie la période de délai d’expiration des jetons de protection des données àt rois heures :
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
options.TokenLifespan = TimeSpan.FromHours(3));
Les jetons utilisateur intégrés Identity (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 des jetons de messagerie, ajoutez un jeton personnalisé DataProtectorTokenProvider<TUser> et 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);
}
}
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.