Einführung in Identity in ASP.NET Core
Von Rick Anderson
ASP.NET Core Identity:
- ist eine API, die die Anmeldefunktionalität der Benutzeroberfläche (UI) unterstützt.
- verwaltet Benutzer*innen, Kennwörter, Profildaten, Rollen, Ansprüche, Token, E-Mail-Bestätigung u. v. m.
Benutzer*innen können ein Konto mit den in Identity gespeicherten Anmeldeinformationen erstellen oder einen externen Anmeldeanbieter verwenden. Zu den unterstützten externen Anmeldeanbietern gehören Facebook, Google, Microsoft-Konto und Twitter.
Informationen dazu, wie global die Authentifizierung aller Benutzer angefordert werden kann, finden Sie unter Authentifizierte Benutzer erforderlich.
Der Quellcode von Identity steht auf GitHub zur Verfügung. Erstellen Sie ein Gerüst für Identity, und überprüfen Sie in den generierten Dateien die Interaktion der Vorlage mit Identity.
Identity wird in der Regel mit einer SQL Server-Datenbank zum Speichern von Benutzernamen, Kennwörtern und Profildaten konfiguriert. Alternativ kann ein anderer persistenter Speicher verwendet werden, z. B. Azure Table Storage.
In diesem Thema erfahren Sie, wie Sie mit Identity Benutzer*innen registrieren, anmelden und abmelden. Hinweis: In den Vorlagen werden Benutzername und E-Mail-Adresse für Benutzer*innen gleich behandelt. Ausführlichere Anweisungen zum Erstellen von Apps, die Identity verwenden, finden Sie unter Nächste Schritte.
ASP.NET Core Identity steht in keinem Zusammenhang mit der Microsoft identity Platform. Microsoft identity Plattform ist:
- eine Weiterentwicklung der Azure AD-Entwicklerplattform (Azure Active Directory).
- eine alternative identityl-Lösung für die Authentifizierung und Autorisierung in ASP.NET Core-Apps.
ASP.NET Core Identity fügt Benutzeroberflächen-Anmeldefunktionen zu ASP.NET Core-Web-Apps hinzu. Verwenden Sie zum Sichern von Web-APIs und SPAs eine der folgenden Optionen:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Server
Duende Identity Server ist ein OpenID Connect- und OAuth 2.0-Framework für ASP.NET Core. Duende Identity Server ermöglicht die folgenden Sicherheitsfeatures:
- Authentifizierung als Dienst
- Einmaliges Anmelden und einmaliges Abmelden für mehrere Anwendungstypen
- Zugriffssteuerung für APIs
- Federation Gateway
Wichtig
Duende Software erhebt ggf. eine Lizenzgebühr für die Nutzung von Duende Identity Server in der Produktion. Weitere Informationen finden Sie unter Migrieren von ASP.NET Core 5.0 zu 6.0.
Weitere Informationen finden Sie in der Dokumentation zu Duende Identity Server (Website von Duende Software).
Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)
Erstellen einer Web-App mit Authentifizierung
Erstellen Sie ein Projekt für eine ASP.NET Core-Webanwendung mit einzelnen Benutzerkonten.
- Wählen Sie die Vorlage ASP.NET Core-Web-App aus. Nennen Sie das Projekt WebApp1, um denselben Namespace wie der Projektdownload zu verwenden. Klicken Sie auf OK.
- Wählen Sie in der Eingabe Authentifizierungstyp die Option Einzelne Benutzerkonten aus.
Das generierte Projekt stellt ASP.NET Core Identity als Razor-Klassenbibliothek bereit. Die IdentityRazor-Klassenbibliothek macht Endpunkte im Identity
-Bereich verfügbar. Beispiel:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Anwenden von Migrationen
Wenden Sie die Migrationen an, um die Datenbank zu initialisieren.
Führen Sie folgenden Befehl in der Paket-Manager-Konsole aus:
Update-Database
Test der Registrierung und Anmeldung
Führen Sie die App aus, und registrieren Sie eine*n neue*n Benutzer*in. Je nach Bildschirmgröße müssen Sie möglicherweise die Umschaltfläche für die Navigation auswählen, um die Links für das Registrieren und Anmelden anzuzeigen.
Anzeigen der Identity-Datenbank
- Wählen Sie im Menü Ansicht den SQL Server-Objekt-Explorer (SSOX) aus.
- Navigieren Sie zu (localdb)MSSQLLocalDB(SQL Server 13). Klicken Sie mit der rechten Maustaste auf dbo.AspNetUsers>Daten anzeigen:
Konfigurieren von Identity-Diensten
Dienste werden in Program.cs
hinzugefügt. Das typische Muster besteht darin, Methoden in der folgenden Reihenfolge aufzurufen:
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();
Der obige Code konfiguriert Identity mit den Standardwerten für die einzelnen Optionen. Dienste werden der App über die Abhängigkeitsinjektion verfügbar gemacht.
Identity wird durch Aufrufen von UseAuthentication aktiviert. UseAuthentication
fügt der Anforderungspipeline Authentifizierungsmiddleware hinzu.
Die mit der Vorlage generierte App verwendet keine Autorisierung. app.UseAuthorization
ist enthalten, um sicherzustellen, dass sie in der richtigen Reihenfolge hinzugefügt wird, wenn die App um eine Autorisierung erweitert wird. UseRouting
, UseAuthentication
und UseAuthorization
müssen in der im vorherigen Code gezeigten Reihenfolge aufgerufen werden.
Weitere Informationen zu IdentityOptions
finden Sie unter IdentityOptions und Starten von Anwendungen.
Erstellen von Gerüsten für Register, Login, LogOut und RegisterConfirmation
Fügen Sie die Dateien Register
, Login
, LogOut
und RegisterConfirmation
hinzu. Befolgen Sie die Anweisungen unter Erstellen eines Gerüsts identity in einem Razor-Projekt mit Autorisierung, um den in diesem Abschnitt gezeigten Code zu generieren.
Überprüfen der Registrierung
Wenn Benutzer*innen auf der Seite Register
die Schaltfläche Register (Registrieren) auswählen, wird die RegisterModel.OnPostAsync
-Aktion aufgerufen. Die Benutzer*innen werden von CreateAsync(TUser) im _userManager
-Objekt erstellt:
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();
}
Deaktivieren der Standardkontoüberprüfung
Bei den Standardvorlagen werden die Benutzer*innen zu Account.RegisterConfirmation
umgeleitet, wo sie einen Link auswählen können, um das Konto bestätigen zu lassen. Die Standardeinstellung von Account.RegisterConfirmation
wird nur für Tests verwendet. Die automatische Kontoüberprüfung sollte in einer Produktions-App deaktiviert werden.
Um ein bestätigtes Konto zu erzwingen und eine sofortige Anmeldung bei der Registrierung zu verhindern, legen Sie DisplayConfirmAccountLink = false
in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
fest:
[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();
}
}
Anmelden
Das Anmeldeformular wird in folgenden Fällen angezeigt:
- Der Link Log in (Anmelden) wird ausgewählt.
- Benutzer*innen versuchen, auf eine eingeschränkte Seite zuzugreifen, für die sie nicht autorisiert sind oder für die sie nicht vom System authentifiziert wurden.
Wenn das Formular auf der Anmeldeseite übermittelt wird, wird die OnPostAsync
-Aktion aufgerufen. PasswordSignInAsync
wird im _signInManager
-Objekt aufgerufen.
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();
}
Informationen zum Treffen von Autorisierungsentscheidungen finden Sie unter Einführung in die Autorisierung in ASP.NET Core.
Abmelden
Der Link Log out (Abmelden) ruft die LogoutModel.OnPost
-Aktion auf.
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();
}
}
}
}
Im obigen Code muss der return RedirectToPage();
-Code eine Umleitung sein, damit der Browser eine neue Anforderung ausführt und die identity der Benutzer*innen aktualisiert wird.
SignOutAsync löscht die in einem cookie gespeicherten Benutzeransprüche.
Die Nachverarbeitung wird in Pages/Shared/_LoginPartial.cshtml
angegeben:
@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>
Testen von Identity
Die Standardvorlagen für Webprojekte erlauben den anonymen Zugriff auf die Startseiten. Fügen Sie zum Testen von Identity [Authorize]
hinzu:
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()
{
}
}
}
Wenn Sie angemeldet sind, melden Sie sich ab. Führen Sie die App aus, und wählen Sie den Link Privacy aus. Sie werden zur Anmeldeseite umgeleitet.
Informationen zu Identity
So erkunden Sie Identity genauer
- Erstellen einer vollständigen identity Quelle für die Benutzeroberfläche
- Untersuchen Sie die Quelle jeder Seite, und durchlaufen Sie den Debugger schrittweise.
Identity Components
Alle von Identity abhängigen NuGet-Pakete sind im freigegebenen ASP.NET Core-Framework enthalten.
Das primäre Paket für Identity ist Microsoft.AspNetCore.Identity. Dieses Paket enthält den Kernsatz von Schnittstellen für ASP.NET Core Identity und wird mit Microsoft.AspNetCore.Identity.EntityFrameworkCore
eingeschlossen.
Migrieren zu ASP.NET Core Identity
Weitere Informationen und Leitfäden zum Migrieren Ihres vorhandenen Identity-Speichers finden Sie unter Migrieren der Authentifizierung und Identity.
Festlegen der Kennwortsicherheit
Unter Konfiguration finden Sie ein Beispiel, mit dem Mindestkennwortanforderungen festgelegt werden.
AddDefaultIdentity und AddIdentity
AddDefaultIdentity wurde in ASP.NET Core 2.1 eingeführt. Ein Aufruf von AddDefaultIdentity
ähnelt dem Aufrufen von Folgendem:
Weitere Informationen finden Sie unter Neue Datenquelle hinzufügen.
Verhindern der Veröffentlichung statischer Identity-Ressourcen
Um die Veröffentlichung statischer Identity-Ressourcen (Stylesheets und JavaScript-Dateien für die Identity-Benutzeroberfläche) im Webstamm zu verhindern, fügen Sie der Projektdatei der App die folgende ResolveStaticWebAssetsInputsDependsOn
-Eigenschaft und das folgende RemoveIdentityAssets
-Ziel hinzu:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Nächste Schritte
- ASP.NET Core -QuellcodeIdentity
- Verwenden von Rollen in ASP.NET Core Identity
- Informationen zum Konfigurieren von Identity mit SQLite finden Sie in diesem GitHub-Issue.
- Konfigurieren von Identity
- Erstellen einer ASP.NET Core-App mit Benutzerdaten, die durch Autorisierung geschützt sind
- Hinzufügen, Herunterladen und Löschen von Identity-Benutzerdaten in einem ASP.NET Core-Projekt
- Enable QR Code generation for authenticator apps in ASP.NET Core (Aktivieren der QR-Code-Generierung für TOTP-Authentifikator-Apps in ASP.NET Core)
- Migrieren von Authentifizierung und Identity zu ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Kontobestätigung und Kennwortwiederherstellung in ASP.NET Core)
- Zwei-Faktor-Authentifizierung per SMS in ASP.NET Core
- Hosten von ASP.NET Core in einer Webfarm
Von Rick Anderson
ASP.NET Core Identity:
- ist eine API, die die Anmeldefunktionalität der Benutzeroberfläche (UI) unterstützt.
- verwaltet Benutzer*innen, Kennwörter, Profildaten, Rollen, Ansprüche, Token, E-Mail-Bestätigung u. v. m.
Benutzer*innen können ein Konto mit den in Identity gespeicherten Anmeldeinformationen erstellen oder einen externen Anmeldeanbieter verwenden. Zu den unterstützten externen Anmeldeanbietern gehören Facebook, Google, Microsoft-Konto und Twitter.
Informationen dazu, wie global die Authentifizierung aller Benutzer angefordert werden kann, finden Sie unter Authentifizierte Benutzer erforderlich.
Der Quellcode von Identity steht auf GitHub zur Verfügung. Erstellen Sie ein Gerüst für Identity, und überprüfen Sie in den generierten Dateien die Interaktion der Vorlage mit Identity.
Identity wird in der Regel mit einer SQL Server-Datenbank zum Speichern von Benutzernamen, Kennwörtern und Profildaten konfiguriert. Alternativ kann ein anderer persistenter Speicher verwendet werden, z. B. Azure Table Storage.
In diesem Thema erfahren Sie, wie Sie mit Identity Benutzer*innen registrieren, anmelden und abmelden. Hinweis: In den Vorlagen werden Benutzername und E-Mail-Adresse für Benutzer*innen gleich behandelt. Ausführlichere Anweisungen zum Erstellen von Apps, die Identity verwenden, finden Sie unter Nächste Schritte.
Microsoft identity Plattform ist:
- eine Weiterentwicklung der Azure AD-Entwicklerplattform (Azure Active Directory).
- eine alternative identityl-Lösung für die Authentifizierung und Autorisierung in ASP.NET Core-Apps.
- nicht mit ASP.NET Core Identity verwandt.
ASP.NET Core Identity fügt Benutzeroberflächen-Anmeldefunktionen zu ASP.NET Core-Web-Apps hinzu. Verwenden Sie zum Sichern von Web-APIs und SPAs eine der folgenden Optionen:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer ist ein Drittanbieterprodukt.
Duende IdentityServer ist ein OpenID Connect und OAuth 2.0 Framework für ASP.NET Core. Duende IdentityServer ermöglicht die folgenden Sicherheitsfeatures:
- Authentifizierung als Dienst
- Einmaliges Anmelden und einmaliges Abmelden für mehrere Anwendungstypen
- Zugriffssteuerung für APIs
- Federation Gateway
Weitere Informationen finden Sie in der Übersicht über Duende IdentityServer.
Weitere Informationen zu anderen Authentifizierungsanbietern finden Sie unter Community-basierte OSS-Authentifizierungsoptionen für ASP.NET Core.
Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)
Erstellen einer Web-App mit Authentifizierung
Erstellen Sie ein Projekt für eine ASP.NET Core-Webanwendung mit einzelnen Benutzerkonten.
- Wählen Sie Datei>Neu>Projekt aus.
- Wählen Sie ASP.NET Core-Webanwendung aus. Nennen Sie das Projekt WebApp1, um denselben Namespace wie der Projektdownload zu verwenden. Klicken Sie auf OK.
- Wählen Sie eine ASP.NET Core-Webanwendung und dann Authentifizierung ändern aus.
- Wählen Sie Einzelne Benutzerkonten und dann OK aus.
Das generierte Projekt stellt ASP.NET Core Identity als Razor-Klassenbibliothek bereit. Die IdentityRazor-Klassenbibliothek macht Endpunkte im Identity
-Bereich verfügbar. Beispiel:
- /Identity/Account/Login
- /Identity/Account/Logout
- /Identity/Account/Manage
Anwenden von Migrationen
Wenden Sie die Migrationen an, um die Datenbank zu initialisieren.
Führen Sie folgenden Befehl in der Paket-Manager-Konsole aus:
PM> Update-Database
Test der Registrierung und Anmeldung
Führen Sie die App aus, und registrieren Sie eine*n neue*n Benutzer*in. Je nach Bildschirmgröße müssen Sie möglicherweise die Umschaltfläche für die Navigation auswählen, um die Links für das Registrieren und Anmelden anzuzeigen.
Anzeigen der Identity-Datenbank
- Wählen Sie im Menü Ansicht den SQL Server-Objekt-Explorer (SSOX) aus.
- Navigieren Sie zu (localdb)MSSQLLocalDB(SQL Server 13). Klicken Sie mit der rechten Maustaste auf dbo.AspNetUsers>Daten anzeigen:
Konfigurieren von Identity-Diensten
Dienste werden in ConfigureServices
hinzugefügt. Das typische Muster besteht darin, alle Add{Service}
-Methoden und dann alle services.Configure{Service}
-Methoden aufzurufen.
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;
});
}
Der obige hervorgehobene Code konfiguriert Identity mit den Standardwerten für die einzelnen Optionen. Dienste werden der App über die Abhängigkeitsinjektion verfügbar gemacht.
Identity wird durch Aufrufen von UseAuthentication aktiviert. UseAuthentication
fügt der Anforderungspipeline Authentifizierungsmiddleware hinzu.
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;
});
}
Der obige Code konfiguriert Identity mit den Standardwerten für die einzelnen Optionen. Dienste werden der App über die Abhängigkeitsinjektion verfügbar gemacht.
Identity wird durch Aufrufen von UseAuthentication aktiviert. UseAuthentication
fügt der Anforderungspipeline Authentifizierungsmiddleware hinzu.
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();
});
}
Die mit der Vorlage generierte App verwendet keine Autorisierung. app.UseAuthorization
ist enthalten, um sicherzustellen, dass sie in der richtigen Reihenfolge hinzugefügt wird, wenn die App um eine Autorisierung erweitert wird. UseRouting
, UseAuthentication
, UseAuthorization
und UseEndpoints
müssen in der im vorherigen Code gezeigten Reihenfolge aufgerufen werden.
Weitere Informationen zu IdentityOptions
und Startup
finden Sie unter IdentityOptions und Starten von Anwendungen.
Erstellen von Gerüsten für Register, Login, LogOut und RegisterConfirmation
Fügen Sie die Dateien Register
, Login
, LogOut
und RegisterConfirmation
hinzu. Befolgen Sie die Anweisungen unter Erstellen eines Gerüsts identity in einem Razor-Projekt mit Autorisierung, um den in diesem Abschnitt gezeigten Code zu generieren.
Überprüfen der Registrierung
Wenn Benutzer*innen auf der Seite Register
die Schaltfläche Register (Registrieren) auswählen, wird die RegisterModel.OnPostAsync
-Aktion aufgerufen. Die Benutzer*innen werden von CreateAsync(TUser) im _userManager
-Objekt erstellt:
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();
}
Deaktivieren der Standardkontoüberprüfung
Bei den Standardvorlagen werden die Benutzer*innen zu Account.RegisterConfirmation
umgeleitet, wo sie einen Link auswählen können, um das Konto bestätigen zu lassen. Die Standardeinstellung von Account.RegisterConfirmation
wird nur für Tests verwendet. Die automatische Kontoüberprüfung sollte in einer Produktions-App deaktiviert werden.
Um ein bestätigtes Konto zu erzwingen und eine sofortige Anmeldung bei der Registrierung zu verhindern, legen Sie DisplayConfirmAccountLink = false
in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs
fest:
[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();
}
}
Anmelden
Das Anmeldeformular wird in folgenden Fällen angezeigt:
- Der Link Log in (Anmelden) wird ausgewählt.
- Benutzer*innen versuchen, auf eine eingeschränkte Seite zuzugreifen, für die sie nicht autorisiert sind oder für die sie nicht vom System authentifiziert wurden.
Wenn das Formular auf der Anmeldeseite übermittelt wird, wird die OnPostAsync
-Aktion aufgerufen. PasswordSignInAsync
wird im _signInManager
-Objekt aufgerufen.
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();
}
Informationen zum Treffen von Autorisierungsentscheidungen finden Sie unter Einführung in die Autorisierung in ASP.NET Core.
Abmelden
Der Link Log out (Abmelden) ruft die LogoutModel.OnPost
-Aktion auf.
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();
}
}
}
}
Im obigen Code muss der return RedirectToPage();
-Code eine Umleitung sein, damit der Browser eine neue Anforderung ausführt und die identity der Benutzer*innen aktualisiert wird.
SignOutAsync löscht die in einem cookie gespeicherten Benutzeransprüche.
Die Nachverarbeitung wird in Pages/Shared/_LoginPartial.cshtml
angegeben:
@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>
Testen von Identity
Die Standardvorlagen für Webprojekte erlauben den anonymen Zugriff auf die Startseiten. Fügen Sie zum Testen von Identity [Authorize]
hinzu:
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()
{
}
}
}
Wenn Sie angemeldet sind, melden Sie sich ab. Führen Sie die App aus, und wählen Sie den Link Privacy aus. Sie werden zur Anmeldeseite umgeleitet.
Informationen zu Identity
So erkunden Sie Identity genauer
- Erstellen einer vollständigen identity Quelle für die Benutzeroberfläche
- Untersuchen Sie die Quelle jeder Seite, und durchlaufen Sie den Debugger schrittweise.
Identity Components
Alle von Identity abhängigen NuGet-Pakete sind im freigegebenen ASP.NET Core-Framework enthalten.
Das primäre Paket für Identity ist Microsoft.AspNetCore.Identity. Dieses Paket enthält den Kernsatz von Schnittstellen für ASP.NET Core Identity und wird mit Microsoft.AspNetCore.Identity.EntityFrameworkCore
eingeschlossen.
Migrieren zu ASP.NET Core Identity
Weitere Informationen und Leitfäden zum Migrieren Ihres vorhandenen Identity-Speichers finden Sie unter Migrieren der Authentifizierung und Identity.
Festlegen der Kennwortsicherheit
Unter Konfiguration finden Sie ein Beispiel, mit dem Mindestkennwortanforderungen festgelegt werden.
Verhindern der Veröffentlichung statischer Identity-Ressourcen
Um die Veröffentlichung statischer Identity-Ressourcen (Stylesheets und JavaScript-Dateien für die Identity-Benutzeroberfläche) im Webstamm zu verhindern, fügen Sie der Projektdatei der App die folgende ResolveStaticWebAssetsInputsDependsOn
-Eigenschaft und das folgende RemoveIdentityAssets
-Ziel hinzu:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Nächste Schritte
- ASP.NET Core -QuellcodeIdentity
- AddDefaultIdentity-Quelle
- Informationen zum Konfigurieren von Identity mit SQLite finden Sie in diesem GitHub-Issue.
- Konfigurieren von Identity
- Erstellen einer ASP.NET Core-App mit Benutzerdaten, die durch Autorisierung geschützt sind
- Hinzufügen, Herunterladen und Löschen von Identity-Benutzerdaten in einem ASP.NET Core-Projekt
- Enable QR Code generation for authenticator apps in ASP.NET Core (Aktivieren der QR-Code-Generierung für TOTP-Authentifikator-Apps in ASP.NET Core)
- Migrieren von Authentifizierung und Identity zu ASP.NET Core
- Account confirmation and password recovery in ASP.NET Core (Kontobestätigung und Kennwortwiederherstellung in ASP.NET Core)
- Zwei-Faktor-Authentifizierung per SMS in ASP.NET Core
- Hosten von ASP.NET Core in einer Webfarm