Présentation de Identity sur ASP.NET Core
Par Rick Anderson
ASP.NET Core Identity :
- Est une API qui prend en charge la fonctionnalité de connexion par interface utilisateur.
- Gère les utilisateurs, les mots de passe, les données de profil, les rôles, les revendications, les jetons, la confirmation par e-mail, etc.
Les utilisateurs peuvent créer un compte avec les informations de connexion stockées dans Identity ou utiliser un fournisseur de connexion externe. Les fournisseurs de connexion externes pris en charge incluent Facebook, Google, Compte Microsoft et Twitter.
Pour plus d’informations sur la façon d’exiger l’authentification globale de tous les utilisateurs, consultez la section Exiger des utilisateurs authentifiés.
Le code source Identity est disponible sur GitHub. Générez automatiquement des modèles Identity et affichez les fichiers générés pour passer en revue l’interaction du modèle avec Identity.
Identity est généralement configuré à l’aide d’une base de données SQL Server pour stocker les noms d’utilisateur, les mots de passe et les données de profil. Vous pouvez également utiliser un autre magasin persistant, par exemple Stockage Table Azure.
Dans cette rubrique, vous allez apprendre à utiliser Identity pour inscrire, connecter et déconnecter un utilisateur. Remarque : les modèles traitent le nom d’utilisateur et l’adresse e-mail comme étant identiques pour les utilisateurs. Pour obtenir des instructions plus détaillées sur la création d’applications qui utilisent Identity, consultez la section Étapes suivantes.
ASP.NET Core Identity n’est pas lié à la plateforme d’identity Microsoft. La plateforme d’identity Microsoft est :
- Une évolution de la plateforme de développement Azure Active Directory (Azure AD).
- Une solution d’identity alternative pour l’authentification et l’autorisation dans les applications ASP.NET Core.
ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Serveur Identity Duende
Duende Identity Server est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :
- Authentification en tant que service (AaaS)
- Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
- Contrôle d’accès pour les API
- Federation Gateway
Important
Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrer de ASP.NET Core 5.0 vers 6.0.
Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).
Affichez ou téléchargez l’exemple de code (procédure de téléchargement).
Créer une application web avec authentification
Créez un projet d’application web ASP.NET Core avec des comptes d’utilisateur individuels.
- Sélectionnez le modèle Application web ASP.NET Core. Nommez le projet WebApp1 pour que l’espace de noms soit le même que le téléchargement du projet. Cliquez sur OK.
- Dans l’entrée Type d’authentification, sélectionnez Comptes d’utilisateur individuels.
Le projet généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor. La bibliothèque de classes IdentityRazor expose les points de terminaison avec la zone Identity
. Par exemple :
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Appliquer des migrations
Appliquez les migrations pour initialiser la base de données.
Exécutez la commande suivante dans la console du Gestionnaire de package (PMC) :
Update-Database
Tester l’inscription et la connexion
Exécutez l’application et inscrivez un utilisateur. Selon la taille de votre écran, vous devrez peut-être sélectionner le bouton bascule de navigation pour afficher les liens d’inscription et de connexion.
Afficher la base de données Identity
- Dans le menu Affichage, sélectionnez Explorateur d’objets SQL Server (SSOX).
- Accédez à (localdb)MSSQLLocalDB(SQL Server 13). Cliquez avec le bouton droit sur dbo.AspNetUsers>Afficher les données :
Configurer les services Identity
Les services sont ajoutés dans Program.cs
. Le modèle classique consiste à appeler les méthodes dans l’ordre suivant :
Add{Service}
builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
builder.Services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
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();
Le code précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.
Identity est activé en appelant UseAuthentication. UseAuthentication
ajoute un intergiciel d’authentification au pipeline de requêtes.
L’application générée par un modèle n’utilise pas l’autorisation. app.UseAuthorization
est inclus pour s’assurer qu’il est ajouté dans l’ordre correct si l’application ajoute une autorisation. UseRouting
, UseAuthentication
et UseAuthorization
doivent être appelés dans l’ordre indiqué dans le code précédent.
Pour plus d’informations sur IdentityOptions
, consultez les articles IdentityOptions et Démarrage d’une application.
Générer automatiquement les modèles Register, Login, LogOut et RegisterConfirmation
Ajoutez les fichiers Register
, Login
, LogOut
et RegisterConfirmation
. Suivez les instructions de la section Générer un modèle d’identity dans un projet Razor avec autorisation pour générer le code présenté dans cette section.
Examiner l’inscription
Quand un utilisateur clique sur le bouton d’inscription sur la page Register
, l’action RegisterModel.OnPostAsync
est appelée. L’utilisateur est créé par CreateAsync(TUser) sur l’objet _userManager
:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation",
new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Désactiver la vérification du compte par défaut
Avec les modèles par défaut, l’utilisateur est redirigé vers Account.RegisterConfirmation
où il peut sélectionner un lien pour que le compte soit confirmé. La valeur par défaut Account.RegisterConfirmation
est utilisée uniquement à des fins de test. La vérification automatique du compte doit être désactivée dans une application de production.
Pour exiger un compte confirmé et empêcher la connexion immédiate lors de l’inscription, définissez DisplayConfirmAccountLink = false
dans /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
:
[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;
}
public string Email { get; set; }
public bool DisplayConfirmAccountLink { get; set; }
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
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();
}
}
Se connecter
Le formulaire de connexion s’affiche dans les cas suivants :
- Le lien de connexion est sélectionné.
- Un utilisateur tente d’accéder à une page restreinte à laquelle il n’est pas autorisé à accéder ou quand il n’a pas été authentifié par le système.
Quand le formulaire de la page de connexion est envoyé, l’action OnPostAsync
est appelée. PasswordSignInAsync
est appelé sur l’objet _signInManager
.
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email,
Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new
{
ReturnUrl = returnUrl,
RememberMe = Input.RememberMe
});
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Pour plus d’informations sur la prise de décisions en ce qui concerne l’autorisation, consultez l’article Présentation de l’autorisation dans ASP.NET Core.
Se déconnecter
Le lien de déconnexion appelle l’action LogoutModel.OnPost
.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace WebApp1.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LogoutModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LogoutModel> _logger;
public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
return RedirectToPage();
}
}
}
}
Dans le code précédent, le code return RedirectToPage();
doit être une redirection afin que le navigateur effectue une nouvelle demande et que l’identity de l’utilisateur soit mise à jour.
SignOutAsync efface les revendications de l’utilisateur stockées dans un cookie.
Post est spécifié dans Pages/Shared/_LoginPartial.cshtml
:
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index"
title="Manage">Hello @User.Identity.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout"
asp-route-returnUrl="@Url.Page("/", new { area = "" })"
method="post" >
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
Tester Identity
Les modèles de projet web par défaut autorisent l’accès anonyme aux pages d’home. Pour tester Identity, ajoutez [Authorize]
:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace WebApp1.Pages
{
[Authorize]
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
Si vous êtes connecté, déconnectez-vous. Exécutez l'application et sélectionnez le lien Privacy. Vous êtes redirigé vers la page de connexion.
Explorer Identity
Pour explorer Identity en détail :
- Créer une source d’interface utilisateur d’identity complète
- Examinez la source de chaque page et effectuez la procédure du débogueur.
Identity Components
Tous les packages NuGet dépendants d’Identity sont inclus dans l’infrastructure partagée ASP.NET Core.
Le package principal pour Identity est Microsoft.AspNetCore.Identity. Ce package contient l’ensemble d’interfaces de base pour ASP.NET Core Identity et est inclus par Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Migration vers ASP.NET Core Identity
Pour plus d’informations et pour obtenir de l’aide sur la migration de votre magasin Identity existant, consultez l’article Migrer l’authentification et Identity.
Définition de la force du mot de passe
Consultez la section sur la configuration pour obtenir un exemple qui définit les exigences minimales relatives aux mots de passe.
AddDefaultIdentity et AddIdentity
AddDefaultIdentity a été introduit dans ASP.NET Core 2.1. L’appel de AddDefaultIdentity
est similaire à l’appel de ce qui suit :
Pour plus d’informations, consultez la section AddDefaultIdentity sources.
Empêcher la publication de ressources Identity statiques
Pour empêcher la publication de ressources Identity statiques (feuilles de style et fichiers JavaScript pour l’interface utilisateur Identity) sur la racine web, ajoutez la propriété et la cible ResolveStaticWebAssetsInputsDependsOn
suivantes RemoveIdentityAssets
au fichier projet de l’application :
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Étapes suivantes
- Consulter ce problème GitHub pour plus d’informations sur la configuration d’Identity à l’aide de SQLite
- Configuration de Identity
- Créer une application ASP.NET Core avec des données utilisateur protégées par une autorisation
- Ajouter, télécharger et supprimer des données utilisateur dans Identity dans un projet ASP.NET Core
- Activer la génération de code QR pour les applications d’authentification TOTP dans ASP.NET Core
- Migrer l’authentification et Identity vers ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Confirmation de compte et récupération de mot de passe dans ASP.NET Core)
- Authentification à deux facteurs avec SMS dans ASP.NET Core
- Hôte ASP.NET Core dans une batterie de serveurs web
Par Rick Anderson
ASP.NET Core Identity :
- Est une API qui prend en charge la fonctionnalité de connexion par interface utilisateur.
- Gère les utilisateurs, les mots de passe, les données de profil, les rôles, les revendications, les jetons, la confirmation par e-mail, etc.
Les utilisateurs peuvent créer un compte avec les informations de connexion stockées dans Identity ou utiliser un fournisseur de connexion externe. Les fournisseurs de connexion externes pris en charge incluent Facebook, Google, Compte Microsoft et Twitter.
Pour plus d’informations sur la façon d’exiger l’authentification globale de tous les utilisateurs, consultez la section Exiger des utilisateurs authentifiés.
Le code source Identity est disponible sur GitHub. Générez automatiquement des modèles Identity et affichez les fichiers générés pour passer en revue l’interaction du modèle avec Identity.
Identity est généralement configuré à l’aide d’une base de données SQL Server pour stocker les noms d’utilisateur, les mots de passe et les données de profil. Vous pouvez également utiliser un autre magasin persistant, par exemple Stockage Table Azure.
Dans cette rubrique, vous allez apprendre à utiliser Identity pour inscrire, connecter et déconnecter un utilisateur. Remarque : les modèles traitent le nom d’utilisateur et l’adresse e-mail comme étant identiques pour les utilisateurs. Pour obtenir des instructions plus détaillées sur la création d’applications qui utilisent Identity, consultez la section Étapes suivantes.
La plateforme d’identity Microsoft est :
- Une évolution de la plateforme de développement Azure Active Directory (Azure AD).
- Une solution d’identity alternative pour l’authentification et l’autorisation dans les applications ASP.NET Core.
- Non liée à ASP.NET Core Identity.
ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer est un produit tiers.
Duende IdentityServer est un framework OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende IdentityServer active les fonctionnalités de sécurité suivantes :
- Authentification en tant que service (AaaS)
- Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
- Contrôle d’accès pour les API
- Federation Gateway
Pour plus d’informations, consultez la section Vue d’ensemble de Duende IdentityServer.
Pour plus d’informations sur les autres fournisseurs d’authentification, consultez Options d’authentification de la communauté Open Source pour ASP.NET Core
Affichez ou téléchargez l’exemple de code (procédure de téléchargement).
Créer une application web avec authentification
Créez un projet d’application web ASP.NET Core avec des comptes d’utilisateur individuels.
- Sélectionnez Fichier>Nouveau>Projet.
- Sélectionnez Application web ASP.NET Core. Nommez le projet WebApp1 pour que l’espace de noms soit le même que le téléchargement du projet. Cliquez sur OK.
- Sélectionnez une application web ASP.NET Core, puis sélectionnez Modifier l’authentification.
- Sélectionnez Comptes d’utilisateur individuels, puis cliquez sur OK.
Le projet généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor. La bibliothèque de classes IdentityRazor expose les points de terminaison avec la zone Identity
. Par exemple :
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Appliquer des migrations
Appliquez les migrations pour initialiser la base de données.
Exécutez la commande suivante dans la console du Gestionnaire de package (PMC) :
PM> Update-Database
Tester l’inscription et la connexion
Exécutez l’application et inscrivez un utilisateur. Selon la taille de votre écran, vous devrez peut-être sélectionner le bouton bascule de navigation pour afficher les liens d’inscription et de connexion.
Afficher la base de données Identity
- Dans le menu Affichage, sélectionnez Explorateur d’objets SQL Server (SSOX).
- Accédez à (localdb)MSSQLLocalDB(SQL Server 13). Cliquez avec le bouton droit sur dbo.AspNetUsers>Afficher les données :
Configurer les services Identity
Les services sont ajoutés dans ConfigureServices
. Le modèle par défaut consiste à appeler toutes les méthodes Add{Service}
, puis toutes les méthodes services.Configure{Service}
.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
// options.UseSqlite(
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
}
Le code mise en surbrillance précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.
Identity est activé en appelant UseAuthentication. UseAuthentication
ajoute un intergiciel d’authentification au pipeline de requêtes.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
// options.UseSqlite(
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
}
Le code précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.
Identity est activé en appelant UseAuthentication. UseAuthentication
ajoute un intergiciel d’authentification au pipeline de requêtes.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
L’application générée par un modèle n’utilise pas l’autorisation. app.UseAuthorization
est inclus pour s’assurer qu’il est ajouté dans l’ordre correct si l’application ajoute une autorisation. UseRouting
, UseAuthentication
, UseAuthorization
et UseEndpoints
doivent être appelés dans l’ordre indiqué dans le code précédent.
Pour plus d’informations sur IdentityOptions
et Startup
, consultez les articles IdentityOptions et Démarrage d’une application.
Générer automatiquement les modèles Register, Login, LogOut et RegisterConfirmation
Ajoutez les fichiers Register
, Login
, LogOut
et RegisterConfirmation
. Suivez les instructions de la section Générer un modèle d’identity dans un projet Razor avec autorisation pour générer le code présenté dans cette section.
Examiner l’inscription
Quand un utilisateur clique sur le bouton d’inscription sur la page Register
, l’action RegisterModel.OnPostAsync
est appelée. L’utilisateur est créé par CreateAsync(TUser) sur l’objet _userManager
:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation",
new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Désactiver la vérification du compte par défaut
Avec les modèles par défaut, l’utilisateur est redirigé vers Account.RegisterConfirmation
où il peut sélectionner un lien pour que le compte soit confirmé. La valeur par défaut Account.RegisterConfirmation
est utilisée uniquement à des fins de test. La vérification automatique du compte doit être désactivée dans une application de production.
Pour exiger un compte confirmé et empêcher la connexion immédiate lors de l’inscription, définissez DisplayConfirmAccountLink = false
dans /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
:
[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;
}
public string Email { get; set; }
public bool DisplayConfirmAccountLink { get; set; }
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
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();
}
}
Se connecter
Le formulaire de connexion s’affiche dans les cas suivants :
- Le lien de connexion est sélectionné.
- Un utilisateur tente d’accéder à une page restreinte à laquelle il n’est pas autorisé à accéder ou quand il n’a pas été authentifié par le système.
Quand le formulaire de la page de connexion est envoyé, l’action OnPostAsync
est appelée. PasswordSignInAsync
est appelé sur l’objet _signInManager
.
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email,
Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new
{
ReturnUrl = returnUrl,
RememberMe = Input.RememberMe
});
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Pour plus d’informations sur la prise de décisions en ce qui concerne l’autorisation, consultez l’article Présentation de l’autorisation dans ASP.NET Core.
Se déconnecter
Le lien de déconnexion appelle l’action LogoutModel.OnPost
.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace WebApp1.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LogoutModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LogoutModel> _logger;
public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
return RedirectToPage();
}
}
}
}
Dans le code précédent, le code return RedirectToPage();
doit être une redirection afin que le navigateur effectue une nouvelle demande et que l’identity de l’utilisateur soit mise à jour.
SignOutAsync efface les revendications de l’utilisateur stockées dans un cookie.
Post est spécifié dans Pages/Shared/_LoginPartial.cshtml
:
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index"
title="Manage">Hello @User.Identity.Name!</a>
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout"
asp-route-returnUrl="@Url.Page("/", new { area = "" })"
method="post" >
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
Tester Identity
Les modèles de projet web par défaut autorisent l’accès anonyme aux pages d’home. Pour tester Identity, ajoutez [Authorize]
:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace WebApp1.Pages
{
[Authorize]
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
Si vous êtes connecté, déconnectez-vous. Exécutez l'application et sélectionnez le lien Privacy. Vous êtes redirigé vers la page de connexion.
Explorer Identity
Pour explorer Identity en détail :
- Créer une source d’interface utilisateur d’identity complète
- Examinez la source de chaque page et effectuez la procédure du débogueur.
Identity Components
Tous les packages NuGet dépendants d’Identity sont inclus dans l’infrastructure partagée ASP.NET Core.
Le package principal pour Identity est Microsoft.AspNetCore.Identity. Ce package contient l’ensemble d’interfaces de base pour ASP.NET Core Identity et est inclus par Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Migration vers ASP.NET Core Identity
Pour plus d’informations et pour obtenir de l’aide sur la migration de votre magasin Identity existant, consultez l’article Migrer l’authentification et Identity.
Définition de la force du mot de passe
Consultez la section sur la configuration pour obtenir un exemple qui définit les exigences minimales relatives aux mots de passe.
Empêcher la publication de ressources Identity statiques
Pour empêcher la publication de ressources Identity statiques (feuilles de style et fichiers JavaScript pour l’interface utilisateur Identity) sur la racine web, ajoutez la propriété et la cible ResolveStaticWebAssetsInputsDependsOn
suivantes RemoveIdentityAssets
au fichier projet de l’application :
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Étapes suivantes
- Code source ASP.NET Core Identity
- AddDefaultIdentity source
- Consulter ce problème GitHub pour plus d’informations sur la configuration d’Identity à l’aide de SQLite
- Configuration de Identity
- Créer une application ASP.NET Core avec des données utilisateur protégées par une autorisation
- Ajouter, télécharger et supprimer des données utilisateur dans Identity dans un projet ASP.NET Core
- Activer la génération de code QR pour les applications d’authentification TOTP dans ASP.NET Core
- Migrer l’authentification et Identity vers ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Confirmation de compte et récupération de mot de passe dans ASP.NET Core)
- Authentification à deux facteurs avec SMS dans ASP.NET Core
- Hôte ASP.NET Core dans une batterie de serveurs web