Introduzione a Identity in ASP.NET Core
ASP.NET Core Identity:
- API che supporta la funzionalità di accesso dell'interfaccia utente.
- Gestisce utenti, password, dati del profilo, ruoli, attestazioni, token, conferma tramite posta elettronica e altro ancora.
Gli utenti possono creare un account con le informazioni di accesso archiviate in Identity oppure possono usare un provider di accesso esterno. I provider di accesso esterni supportati includono Facebook, Google, Account Microsoft e Twitter.
Per informazioni su come richiedere a livello globale l'autenticazione di tutti gli utenti, vedere Richiedere utenti autenticati.
Il Identity codice sorgente è disponibile in GitHub. Eseguire lo scaffolding Identity e visualizzare i file generati per esaminare l'interazione del modello con Identity.
Identity viene in genere configurato usando un database di SQL Server per archiviare nomi utente, password e dati del profilo. In alternativa, è possibile usare un altro archivio permanente, ad esempio Archiviazione tabelle di Azure.
In questo argomento si apprenderà come usare Identity per registrare, accedere e disconnettere un utente. Nota: i modelli trattano nome utente e posta elettronica come gli stessi per gli utenti. Per istruzioni più dettagliate sulla creazione di app che usano Identity, vedere Passaggi successivi.
ASP.NET Core Identity non è correlato alla piattaforma Microsoftidentity. La piattaforma Microsoft identity è:
- Evoluzione della piattaforma per sviluppatori di Azure Active Directory (Azure AD).
- Soluzione alternativa identity per l'autenticazione e l'autorizzazione nelle app ASP.NET Core.
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende Identity Server abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Importante
Duende Software potrebbe richiedere il pagamento di una tariffa di licenza per l'uso in produzione di Duende Identity Server. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 5.0 a 6.0.
Per altre informazioni, vedere la documentazione di Duende Server (sito Web duende Identity Software).
Visualizzare o scaricare il codice di esempio (come scaricare).
Creare un'app Web con l'autenticazione
Creare un progetto di applicazione Web di base ASP.NET con singoli account utente.
- Selezionare il modello App Web ASP.NET Core. Denominare il progetto WebApp1 per avere lo stesso spazio dei nomi del download del progetto. Fare clic su OK.
- Per Tipo di autenticazione, selezionare Account utente individuali.
Il progetto generato fornisce ASP.NET Core Identitycome libreria di Razor classi. La IdentityRazor libreria di classi espone gli endpoint con l'area Identity
. Ad esempio:
- /Identity/Account/Login
- /Identity/Account/Disconnessione
- /Identity/Account/Manage
Applicare le migrazioni
Applicare le migrazioni per inizializzare il database.
Eseguire il comando seguente nella console Gestione pacchetti (PMC):
Update-Database
Test Register and Login
Eseguire l'app e registrare un utente. A seconda delle dimensioni dello schermo, potrebbe essere necessario selezionare l'interruttore di spostamento per visualizzare i collegamenti Registra e Account di accesso .
Visualizzare il Identity database
- Scegliere SQL Server Esplora oggetti (SSOX) dal menu Visualizza.
- Passare a (localdb)MSSQLLocalDB(SQL Server 13). Fare clic con il pulsante destro del mouse su dbo. AspNetUsers>Visualizza dati:
Configurare i Identity servizi
I servizi vengono aggiunti in Program.cs
. Il modello tipico consiste nel chiamare i metodi nell'ordine seguente:
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();
Il codice precedente viene configurato Identity con valori di opzione predefiniti. I servizi vengono resi disponibili all'app tramite l'inserimento delle dipendenze.
Identity è abilitato chiamando UseAuthentication. UseAuthentication
aggiunge il middleware di autenticazione alla pipeline di richiesta.
L'app generata dal modello non usa l'autorizzazione. app.UseAuthorization
è incluso per assicurarsi che venga aggiunto nell'ordine corretto se l'app aggiunge l'autorizzazione. UseRouting
, UseAuthentication
e UseAuthorization
devono essere chiamati nell'ordine indicato nel codice precedente.
Per altre informazioni su IdentityOptions
, vedere IdentityOptions e Avvio dell'applicazione.
Eseguire lo scaffolding di Register, Login, LogOut e RegisterConfirmation
Aggiungere i Register
file , LogOut
Login
, e RegisterConfirmation
. Seguire lo scaffolding identity in un Razor progetto con le istruzioni di autorizzazione per generare il codice illustrato in questa sezione.
Esaminare il registro
Quando un utente fa clic sul pulsante Registra nella Register
pagina, viene richiamata l'azione RegisterModel.OnPostAsync
. L'utente viene creato dall'oggetto CreateAsync(TUser) _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();
}
Disabilitare la verifica dell'account predefinita
Con i modelli predefiniti, l'utente viene reindirizzato alla Account.RegisterConfirmation
posizione in cui può selezionare un collegamento per confermare l'account. Il valore predefinito viene usato solo per i test, la verifica automatica dell'account deve essere disabilitata Account.RegisterConfirmation
in un'app di produzione.
Per richiedere un account confermato e impedire l'accesso immediato durante la registrazione, impostare DisplayConfirmAccountLink = false
in /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();
}
}
Accesso
Il modulo Login viene visualizzato quando:
- Il collegamento Accedi è selezionato.
- Un utente tenta di accedere a una pagina con restrizioni che non è autorizzata ad accedere o quando non è stata autenticata dal sistema.
Quando viene inviato il modulo nella pagina Account di accesso, viene chiamata l'azione OnPostAsync
. PasswordSignInAsync
viene chiamato sull'oggetto _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();
}
Per informazioni su come prendere decisioni di autorizzazione, vedere Introduzione all'autorizzazione in ASP.NET Core.
Effettuare la disconnessione
Il collegamento Disconnettersi richiama l'azione 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();
}
}
}
}
Nel codice precedente, il codice return RedirectToPage();
deve essere un reindirizzamento in modo che il browser esegua una nuova richiesta e che per identity l'utente venga aggiornato.
SignOutAsync cancella le attestazioni dell'utente archiviate in un oggetto cookie.
Post è specificato in 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>
Test Identity
I modelli di progetto Web predefiniti consentono l'accesso anonimo alle home pagine. Per testare Identity, aggiungere [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()
{
}
}
}
Se è stato eseguito l'accesso, disconnettersi. Eseguire l'app e selezionare il Privacy collegamento. Si verrà reindirizzati alla pagina di accesso.
Esplora Identity
Per esplorare Identity in modo più dettagliato:
- Creare un'origine completa identity dell'interfaccia utente
- Esaminare l'origine di ogni pagina ed eseguire il debugger.
Identity Components
Tutti i Identitypacchetti NuGet dipendenti da sono inclusi nel framework condiviso di ASP.NET Core.
Il pacchetto primario per Identity è Microsoft.AspNetCore.Identity. Questo pacchetto contiene il set di base di interfacce per ASP.NET Core Identityed è incluso da Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Migrazione a ASP.NET Core Identity
Per altre informazioni e indicazioni sulla migrazione dell'archivio esistente Identity , vedere Eseguire la migrazione dell'autenticazione e Identity.
Impostazione della complessità della password
Vedere Configurazione per un esempio che imposta i requisiti minimi per le password.
AddDefaultIdentity e AddIdentity
AddDefaultIdentity è stato introdotto in ASP.NET Core 2.1. La chiamata AddDefaultIdentity
è simile alla chiamata seguente:
Per altre informazioni, vedere AddDefaultIdentity source (Origine AddDefaultIdentity).
Impedire la pubblicazione di asset statici Identity
Per impedire la pubblicazione di asset statici Identity (fogli di stile e file JavaScript per Identity l'interfaccia utente) nella radice Web, aggiungere la proprietà RemoveIdentityAssets
e la destinazione seguenti ResolveStaticWebAssetsInputsDependsOn
al file di progetto dell'app:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Passaggi successivi
- Per informazioni sulla configurazione Identity con SQLite, vedere questo problema di GitHub.
- Configurare Identity
- Creare un'app ASP.NET Core con i dati utente protetti da autorizzazione
- Aggiungere, scaricare ed eliminare i dati Identity utente in un progetto ASP.NET Core
- Abilitare la generazione di codice a matrice per le app di autenticazione TOTP in ASP.NET Core
- Eseguire la migrazione dell'autenticazione e Identity a ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Conferma dell'account e recupero della password in ASP.NET Core)
- Autenticazione a due fattori con SMS in ASP.NET Core
- Ospitare ASP.NET Core in una web farm
ASP.NET Core Identity:
- API che supporta la funzionalità di accesso dell'interfaccia utente.
- Gestisce utenti, password, dati del profilo, ruoli, attestazioni, token, conferma tramite posta elettronica e altro ancora.
Gli utenti possono creare un account con le informazioni di accesso archiviate in Identity oppure possono usare un provider di accesso esterno. I provider di accesso esterni supportati includono Facebook, Google, Account Microsoft e Twitter.
Per informazioni su come richiedere a livello globale l'autenticazione di tutti gli utenti, vedere Richiedere utenti autenticati.
Il Identity codice sorgente è disponibile in GitHub. Eseguire lo scaffolding Identity e visualizzare i file generati per esaminare l'interazione del modello con Identity.
Identity viene in genere configurato usando un database di SQL Server per archiviare nomi utente, password e dati del profilo. In alternativa, è possibile usare un altro archivio permanente, ad esempio Archiviazione tabelle di Azure.
In questo argomento si apprenderà come usare Identity per registrare, accedere e disconnettere un utente. Nota: i modelli trattano nome utente e posta elettronica come gli stessi per gli utenti. Per istruzioni più dettagliate sulla creazione di app che usano Identity, vedere Passaggi successivi.
La piattaforma Microsoft identity è:
- Evoluzione della piattaforma per sviluppatori di Azure Active Directory (Azure AD).
- Soluzione alternativa identity per l'autenticazione e l'autorizzazione nelle app ASP.NET Core.
- Non correlato a ASP.NET Core Identity.
ASP.NET Core Identity aggiunge funzionalità di accesso dell'interfaccia utente alle app Web core ASP.NET. Per proteggere le API Web e i contratti a pagina singola, usare una delle opzioni seguenti:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer è un prodotto di terze parti.
Duende IdentityServer è un framework OpenID Connect e OAuth 2.0 per ASP.NET Core. Duende IdentityServer abilita le funzionalità di sicurezza seguenti:
- Autenticazione come servizio (AaaS)
- Single Sign-On/off (SSO) su più tipi di applicazione
- Controllo di accesso per le API
- Gateway federativo
Per altre informazioni, vedere Panoramica di Duende IdentityServer.
Per altre informazioni su altri provider di autenticazione, vedere Opzioni di autenticazione del sistema operativo della community per ASP.NET Core
Visualizzare o scaricare il codice di esempio (come scaricare).
Creare un'app Web con l'autenticazione
Creare un progetto di applicazione Web di base ASP.NET con singoli account utente.
- Selezionare File>New (Nuovo) >Project (Progetto).
- Selezionare Applicazione Web ASP.NET Core. Denominare il progetto WebApp1 per avere lo stesso spazio dei nomi del download del progetto. Fare clic su OK.
- Selezionare un'applicazione Web principale ASP.NET, quindi selezionare Modifica autenticazione.
- Selezionare Account utente singoli e fare clic su OK.
Il progetto generato fornisce ASP.NET Core Identitycome libreria di Razor classi. La IdentityRazor libreria di classi espone gli endpoint con l'area Identity
. Ad esempio:
- /Identity/Account/Login
- /Identity/Account/Disconnessione
- /Identity/Account/Manage
Applicare le migrazioni
Applicare le migrazioni per inizializzare il database.
Eseguire il comando seguente nella console Gestione pacchetti (PMC):
PM> Update-Database
Test Register and Login
Eseguire l'app e registrare un utente. A seconda delle dimensioni dello schermo, potrebbe essere necessario selezionare l'interruttore di spostamento per visualizzare i collegamenti Registra e Account di accesso .
Visualizzare il Identity database
- Scegliere SQL Server Esplora oggetti (SSOX) dal menu Visualizza.
- Passare a (localdb)MSSQLLocalDB(SQL Server 13). Fare clic con il pulsante destro del mouse su dbo. AspNetUsers>Visualizza dati:
Configurare i Identity servizi
I servizi vengono aggiunti in ConfigureServices
. Il modello tipico consiste nel chiamare tutti i metodi Add{Service}
e quindi chiamare tutti i metodi 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;
});
}
Il codice evidenziato precedente viene configurato Identity con i valori di opzione predefiniti. I servizi vengono resi disponibili all'app tramite l'inserimento delle dipendenze.
Identity è abilitato chiamando UseAuthentication. UseAuthentication
aggiunge il middleware di autenticazione alla pipeline di richiesta.
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;
});
}
Il codice precedente viene configurato Identity con valori di opzione predefiniti. I servizi vengono resi disponibili all'app tramite l'inserimento delle dipendenze.
Identity è abilitato chiamando UseAuthentication. UseAuthentication
aggiunge il middleware di autenticazione alla pipeline di richiesta.
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'app generata dal modello non usa l'autorizzazione. app.UseAuthorization
è incluso per assicurarsi che venga aggiunto nell'ordine corretto se l'app aggiunge l'autorizzazione. UseRouting
UseAuthorization
, UseAuthentication
, e UseEndpoints
devono essere chiamati nell'ordine indicato nel codice precedente.
Per altre informazioni su IdentityOptions
e , vedere IdentityOptions e Startup
Avvio dell'applicazione.
Eseguire lo scaffolding di Register, Login, LogOut e RegisterConfirmation
Aggiungere i Register
file , LogOut
Login
, e RegisterConfirmation
. Seguire lo scaffolding identity in un Razor progetto con le istruzioni di autorizzazione per generare il codice illustrato in questa sezione.
Esaminare il registro
Quando un utente fa clic sul pulsante Registra nella Register
pagina, viene richiamata l'azione RegisterModel.OnPostAsync
. L'utente viene creato dall'oggetto CreateAsync(TUser) _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();
}
Disabilitare la verifica dell'account predefinita
Con i modelli predefiniti, l'utente viene reindirizzato alla Account.RegisterConfirmation
posizione in cui può selezionare un collegamento per confermare l'account. Il valore predefinito viene usato solo per i test, la verifica automatica dell'account deve essere disabilitata Account.RegisterConfirmation
in un'app di produzione.
Per richiedere un account confermato e impedire l'accesso immediato durante la registrazione, impostare DisplayConfirmAccountLink = false
in /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();
}
}
Accesso
Il modulo Login viene visualizzato quando:
- Il collegamento Accedi è selezionato.
- Un utente tenta di accedere a una pagina con restrizioni che non è autorizzata ad accedere o quando non è stata autenticata dal sistema.
Quando viene inviato il modulo nella pagina Account di accesso, viene chiamata l'azione OnPostAsync
. PasswordSignInAsync
viene chiamato sull'oggetto _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();
}
Per informazioni su come prendere decisioni di autorizzazione, vedere Introduzione all'autorizzazione in ASP.NET Core.
Effettuare la disconnessione
Il collegamento Disconnettersi richiama l'azione 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();
}
}
}
}
Nel codice precedente, il codice return RedirectToPage();
deve essere un reindirizzamento in modo che il browser esegua una nuova richiesta e che per identity l'utente venga aggiornato.
SignOutAsync cancella le attestazioni dell'utente archiviate in un oggetto cookie.
Post è specificato in 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>
Test Identity
I modelli di progetto Web predefiniti consentono l'accesso anonimo alle home pagine. Per testare Identity, aggiungere [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()
{
}
}
}
Se è stato eseguito l'accesso, disconnettersi. Eseguire l'app e selezionare il Privacy collegamento. Si verrà reindirizzati alla pagina di accesso.
Esplora Identity
Per esplorare Identity in modo più dettagliato:
- Creare un'origine completa identity dell'interfaccia utente
- Esaminare l'origine di ogni pagina ed eseguire il debugger.
Identity Components
Tutti i Identitypacchetti NuGet dipendenti da sono inclusi nel framework condiviso di ASP.NET Core.
Il pacchetto primario per Identity è Microsoft.AspNetCore.Identity. Questo pacchetto contiene il set di base di interfacce per ASP.NET Core Identityed è incluso da Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Migrazione a ASP.NET Core Identity
Per altre informazioni e indicazioni sulla migrazione dell'archivio esistente Identity , vedere Eseguire la migrazione dell'autenticazione e Identity.
Impostazione della complessità della password
Vedere Configurazione per un esempio che imposta i requisiti minimi per le password.
Impedire la pubblicazione di asset statici Identity
Per impedire la pubblicazione di asset statici Identity (fogli di stile e file JavaScript per Identity l'interfaccia utente) nella radice Web, aggiungere la proprietà RemoveIdentityAssets
e la destinazione seguenti ResolveStaticWebAssetsInputsDependsOn
al file di progetto dell'app:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Passaggi successivi
- codice sorgente ASP.NET Core Identity
- Origine AddDefaultIdentity
- Per informazioni sulla configurazione Identity con SQLite, vedere questo problema di GitHub.
- Configurare Identity
- Creare un'app ASP.NET Core con i dati utente protetti da autorizzazione
- Aggiungere, scaricare ed eliminare i dati Identity utente in un progetto ASP.NET Core
- Abilitare la generazione di codice a matrice per le app di autenticazione TOTP in ASP.NET Core
- Eseguire la migrazione dell'autenticazione e Identity a ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Conferma dell'account e recupero della password in ASP.NET Core)
- Autenticazione a due fattori con SMS in ASP.NET Core
- Ospitare ASP.NET Core in una web farm