Einführung in Identity ASP.NET Core

Von Rick Anderson

ASP.NET Core Identity:

  • Ist eine API, die die Anmeldefunktionen der Benutzeroberfläche unterstützt.
  • Ist so konzipiert, dass sie zusammen mit Duende IdentityServer4 verwendet werden soll.
  • Verwaltet Benutzer, Kennwörter, Profildaten, Rollen, Ansprüche, Token, E-Mail-Bestätigung und vieles mehr.

Benutzer können ein Konto mit den anmeldeinformationen erstellen, die gespeichert sind Identity , oder sie können einen externen Anmeldeanbieter verwenden. Unterstützte externe Anmeldeanbieter umfassen Facebook, Google, Microsoft-Konto und Twitter.

Informationen dazu, wie global die Authentifizierung aller Benutzer angefordert werden kann, finden Sie unter Authentifizierte Benutzer erforderlich.

Der Identity Quellcode ist auf GitHub verfügbar. Gerüst Identity und zeigen Sie die generierten Dateien an, um die Vorlageninteraktion mit Identity.

Identityist in der Regel mithilfe einer SQL Server Datenbank zum Speichern von Benutzernamen, Kennwörtern und Profildaten konfiguriert. Alternativ kann ein anderer beständiger Speicher verwendet werden, z. B. Azure Table Storage.

In diesem Thema erfahren Sie, wie Identity Sie einen Benutzer registrieren, anmelden und abmelden können. Hinweis: Die Vorlagen behandeln Benutzernamen und E-Mails genauso für Benutzer. Ausführlichere Anweisungen zum Erstellen von Apps, die verwendet werden Identity, finden Sie in den nächsten Schritten.

Microsoft Identity Platform ist:

  • Eine Entwicklung der Azure Active Directory (Azure AD)-Entwicklerplattform.
  • Eine alternative Identitätslösung für Authentifizierung und Autorisierung in ASP.NET Core Apps.
  • Nicht im Zusammenhang mit ASP.NET Core Identity.

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:

IdentityServer4 ist ein OpenID Connect- und OAuth 2.0-Framework für ASP.NET Core. IdentityServer4 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 unter Willkommen bei IdentityServer4.

Anzeigen oder Herunterladen des Beispielcodes (herunterladen).

Erstellen einer Web-App mit Authentifizierung

Erstellen Sie ein ASP.NET Core Webanwendungsprojekt mit einzelnen Benutzerkonten.

  • Wählen Sie die ASP.NET Core Web App-Vorlage aus. Benennen Sie das Projekt WebApp1 , um denselben Namespace wie der Projektdownload zu haben. Klicken Sie auf OK.
  • Wählen Sie in der Eingabe des Authentifizierungstypseinzelne Benutzerkonten aus.

Das generierte Projekt stellt eine Razor Klassenbibliothek bereitASP.NET Core Identity. Die IdentityRazor Klassenbibliothek macht Endpunkte mit dem Identity Bereich verfügbar. Beispiel:

  • /Identity/Konto/Anmeldung
  • /Identity/Konto/Abmelden
  • /Identity/Account/Manage

Anwenden von Migrationen

Wenden Sie die Migrationen an, um die Datenbank zu initialisieren.

Führen Sie den folgenden Befehl in der Paket-Manager Konsole (PMC) aus:

Update-Database

Registrieren und Anmelden testen

Führen Sie die App aus, und registrieren Sie einen Benutzer. Je nach Bildschirmgröße müssen Sie möglicherweise die Umschaltfläche für die Navigation auswählen, um die Links " Registrieren " und " Anmelden " anzuzeigen.

Anzeigen der Identity Datenbank

  • Wählen Sie im Menü "Ansicht" SQL Server Objekt-Explorer (SSOX) aus.
  • Navigieren Sie zu (localdb)MSSQLLocalDB(SQL Server 13). Klicken Sie mit der rechten Maustaste auf dbo. AspNetUsersView-Daten>:

Contextual menu on AspNetUsers table in SQL Server Object Explorer

Konfigurieren von Identity Diensten

Dienste werden hinzugefügt.Program.cs Das typische Muster besteht darin, Methoden in der folgenden Reihenfolge aufzurufen:

  1. Add{Service}
  2. 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 vorherige Code konfiguriert sich Identity mit Standardoptionswerten. Dienste werden der App über die Abhängigkeitseinfügung zur Verfügung gestellt.

Identity wird durch Aufrufen UseAuthenticationaktiviert. UseAuthentication Fügt der Anforderungspipeline Authentifizierungs-Middleware hinzu.

Die von 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-Autorisierung hinzugefügt wird. UseRouting, UseAuthenticationund UseAuthorization muss in der Reihenfolge aufgerufen werden, die im vorherigen Code angezeigt wird.

Weitere Informationen finden IdentityOptionsSie unter IdentityOptions und Anwendungsstart.

Gerüstregister, Anmeldung, LogOut und RegisterConfirmation

Fügen Sie die RegisterDateien LogOutLogin, und RegisterConfirmation Dateien hinzu. Folgen Sie der Gerüstidentität in einem Razor Projekt mit Autorisierungsanweisungen , um den in diesem Abschnitt gezeigten Code zu generieren.

Register untersuchen

Wenn ein Benutzer auf die Schaltfläche " Registrieren " auf der Register Seite klickt, wird die RegisterModel.OnPostAsync Aktion aufgerufen. Der Benutzer wird von CreateAsync(TUser) dem _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

Mit den Standardvorlagen wird der Benutzer an die Stelle weitergeleitet, an der Account.RegisterConfirmation er einen Link auswählen kann, um das Konto bestätigt zu haben. Der Standardwert Account.RegisterConfirmation wird nur zum Testen verwendet, die automatische Kontoüberprüfung sollte in einer Produktions-App deaktiviert werden.

Um ein bestätigtes Konto zu erfordern und die sofortige Anmeldung bei der Registrierung zu verhindern, legen Sie folgendes /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.csfestDisplayConfirmAccountLink = false:

[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 angezeigt, wenn:

  • Der Link "Anmelden " ist ausgewählt.
  • Ein Benutzer versucht, auf eine eingeschränkte Seite zuzugreifen, die nicht für den Zugriff autorisiert ist oder wenn er nicht vom System authentifiziert wurde.

Wenn das Formular auf der Anmeldeseite übermittelt wird, wird die OnPostAsync Aktion aufgerufen. PasswordSignInAsync wird für das _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 in der Einführung in die Autorisierung in ASP.NET Core.

Abmelden

Der Link "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 vorherigen Code muss der Code return RedirectToPage(); eine Umleitung sein, damit der Browser eine neue Anforderung ausführt und die Identität für den Benutzer aktualisiert wird.

SignOutAsync löscht die Ansprüche des Benutzers, die in einem cookie.

Post wird in der :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

Die Standardmäßigen Webprojektvorlagen ermöglichen anonymen Zugriff auf die Homepages. Zum Testen Identityfügen Sie Folgendes hinzu [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()
        {
        }
    }
}

Wenn Sie angemeldet sind, melden Sie sich ab. Führen Sie die App aus, und wählen Sie den Privacy Link aus. Sie werden zur Anmeldeseite umgeleitet.

Erkunden Identity

Identity Weitere Informationen finden Sie unter:

Identity Komponenten

IdentityAlle -abhängigen NuGet Pakete sind im ASP.NET Core freigegebenen Framework enthalten.

Das primäre Paket für IdentityMicrosoft.AspNetCore.Identity. Dieses Paket enthält den Kernsatz von Schnittstellen für ASP.NET Core Identity, und wird von Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migrieren zu ASP.NET Core Identity

Weitere Informationen und Anleitungen zum Migrieren Ihres vorhandenen Identity Speichers finden Sie unter Migrieren der Authentifizierung und Identity.

Festlegen der Kennwortstärke

Siehe Konfiguration für ein Beispiel, das die Mindestkennwortanforderungen festlegt.

AddDefaultIdentity und AddIdentity

AddDefaultIdentitywurde in ASP.NET Core 2.1 eingeführt. Anrufe ähneln dem Aufrufen der folgenden Schritte AddDefaultIdentity :

Weitere Informationen finden Sie in der AddDefault-QuelleIdentity.

Verhindern der Veröffentlichung statischer Identity Ressourcen

Um die Veröffentlichung statischer Identity Objekte (Stylesheets und JavaScript-Dateien für Identity ui) im Webstamm zu verhindern, fügen Sie die folgende ResolveStaticWebAssetsInputsDependsOn Eigenschaft und RemoveIdentityAssets das Ziel der Projektdatei der App hinzu:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Nächste Schritte

Von Rick Anderson

ASP.NET Core Identity:

  • Ist eine API, die die Anmeldefunktionen der Benutzeroberfläche unterstützt.
  • Ist so konzipiert, dass sie zusammen mit Duende IdentityServer4 verwendet werden soll.
  • Verwaltet Benutzer, Kennwörter, Profildaten, Rollen, Ansprüche, Token, E-Mail-Bestätigung und vieles mehr.

Benutzer können ein Konto mit den anmeldeinformationen erstellen, die gespeichert sind Identity , oder sie können einen externen Anmeldeanbieter verwenden. Unterstützte externe Anmeldeanbieter umfassen Facebook, Google, Microsoft-Konto und Twitter.

Informationen dazu, wie global die Authentifizierung aller Benutzer angefordert werden kann, finden Sie unter Authentifizierte Benutzer erforderlich.

Der Identity Quellcode ist auf GitHub verfügbar. Gerüst Identity und zeigen Sie die generierten Dateien an, um die Vorlageninteraktion mit Identity.

Identityist in der Regel mithilfe einer SQL Server Datenbank zum Speichern von Benutzernamen, Kennwörtern und Profildaten konfiguriert. Alternativ kann ein anderer beständiger Speicher verwendet werden, z. B. Azure Table Storage.

In diesem Thema erfahren Sie, wie Identity Sie einen Benutzer registrieren, anmelden und abmelden können. Hinweis: Die Vorlagen behandeln Benutzernamen und E-Mails genauso für Benutzer. Ausführlichere Anweisungen zum Erstellen von Apps, die verwendet werden Identity, finden Sie in den nächsten Schritten.

Microsoft Identity Platform ist:

  • Eine Entwicklung der Azure Active Directory (Azure AD)-Entwicklerplattform.
  • Eine alternative Identitätslösung für Authentifizierung und Autorisierung in ASP.NET Core Apps.
  • Nicht im Zusammenhang mit ASP.NET Core Identity.

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:

IdentityServer4 ist ein OpenID Connect- und OAuth 2.0-Framework für ASP.NET Core. IdentityServer4 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 unter Willkommen bei IdentityServer4.

Anzeigen oder Herunterladen des Beispielcodes (herunterladen).

Erstellen einer Web-App mit Authentifizierung

Erstellen Sie ein ASP.NET Core Webanwendungsprojekt mit einzelnen Benutzerkonten.

  • Wählen Sie DateiNeuProjekt aus.
  • Wählen Sie ASP.NET Core-Webanwendung aus. Benennen Sie das Projekt WebApp1 , um denselben Namespace wie der Projektdownload zu haben. Klicken Sie auf OK.
  • Wählen Sie eine ASP.NET Core Webanwendung aus, und wählen Sie dann "Authentifizierung ändern" aus.
  • Wählen Sie einzelne Benutzerkonten aus, und klicken Sie auf 'OK'.

Das generierte Projekt stellt eine Razor Klassenbibliothek bereitASP.NET Core Identity. Die IdentityRazor Klassenbibliothek macht Endpunkte mit dem Identity Bereich verfügbar. Beispiel:

  • /Identity/Konto/Anmeldung
  • /Identity/Konto/Abmelden
  • /Identity/Account/Manage

Anwenden von Migrationen

Wenden Sie die Migrationen an, um die Datenbank zu initialisieren.

Führen Sie den folgenden Befehl in der Paket-Manager Konsole (PMC) aus:

PM> Update-Database

Registrieren und Anmelden testen

Führen Sie die App aus, und registrieren Sie einen Benutzer. Je nach Bildschirmgröße müssen Sie möglicherweise die Navigationsschaltfläche auswählen, um die Links " Registrieren " und "Anmeldung " anzuzeigen.

Anzeigen der Identity Datenbank

  • Wählen Sie im Menü "Ansicht" SQL Server Objekt-Explorer (SSOX) aus.
  • Navigieren Sie zu (localdb)MSSQLLocalDB(SQL Server 13). Klicken Sie mit der rechten Maustaste auf dbo. AspNetUsersView-Daten>:

Contextual menu on AspNetUsers table in SQL Server Object Explorer

Konfigurieren von Identity Diensten

Dienste werden in ConfigureServiceshinzugefü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 vorherige hervorgehobene Code konfiguriert mit Standardwerten Identity . Dienste werden über abhängigkeitsbasierte Injektion für die App zur Verfügung gestellt.

Identity wird durch Aufrufen UseAuthenticationaktiviert. UseAuthentication Fügt die Authentifizierungs-Middleware zur Anforderungspipeline 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 vorherige Code konfiguriert Identity mit Standardoptionswerten. Dienste werden über abhängigkeitsbasierte Injektion für die App zur Verfügung gestellt.

Identity wird durch Aufrufen UseAuthenticationaktiviert. UseAuthentication Fügt die Authentifizierungs-Middleware zur Anforderungspipeline 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 generierte Vorlage verwendet keine Autorisierung. app.UseAuthorization ist enthalten, um sicherzustellen, dass sie in der richtigen Reihenfolge hinzugefügt wird, wenn die App-Autorisierung hinzugefügt wird. UseRouting, UseAuthentication, UseAuthorization, und UseEndpoints muss in der Reihenfolge aufgerufen werden, die im vorherigen Code angezeigt wird.

Weitere Informationen zu IdentityOptions und , finden Sie unter IdentityOptions und StartupAnwendungsstart.

Gerüstregister, Anmeldung, LogOut und RegisterConfirmation

Fügen Sie die Register, LogOutLoginund RegisterConfirmation Dateien hinzu. Folgen Sie der Gerüstidentität in ein Razor Projekt mit Autorisierungsanweisungen , um den in diesem Abschnitt gezeigten Code zu generieren.

Register überprüfen

Wenn ein Benutzer auf die Schaltfläche " Registrieren " auf der Register Seite klickt, wird die RegisterModel.OnPostAsync Aktion aufgerufen. Der Benutzer wird auf CreateAsync(TUser) dem _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

Mit den Standardvorlagen wird der Benutzer an die Stelle weitergeleitet, an der Account.RegisterConfirmation sie einen Link auswählen können, um das Konto bestätigt zu haben. Die Standardeinstellung 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 benötigen und die sofortige Anmeldung bei der Registrierung zu verhindern, legen Sie folgendes /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.csfestDisplayConfirmAccountLink = false:

[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 angezeigt, wenn:

  • Der Link " Anmelden " ist ausgewählt.
  • Ein Benutzer versucht, auf eine eingeschränkte Seite zuzugreifen, auf die sie nicht autorisiert sind oder wenn sie nicht vom System authentifiziert wurden.

Wenn das Formular auf der Anmeldeseite übermittelt wird, wird die OnPostAsync Aktion aufgerufen. PasswordSignInAsync wird auf das _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 in der Einführung in die Autorisierung in ASP.NET Core.

Abmelden

Der Link "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 vorherigen Code muss der Code return RedirectToPage(); eine Umleitung sein, damit der Browser eine neue Anforderung ausführt und die Identität für den Benutzer aktualisiert wird.

SignOutAsync löscht die Ansprüche des Benutzers, die in einem cookie.

Der Beitrag wird im Abschnitt 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

Die Standardwebprojektvorlagen ermöglichen anonymen Zugriff auf die Startseiten. So testen IdentitySie , fügen Sie folgendes hinzu [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()
        {
        }
    }
}

Wenn Sie angemeldet sind, melden Sie sich ab. Führen Sie die App aus, und wählen Sie den Privacy Link aus. Sie werden zur Anmeldeseite umgeleitet.

Erkunden Identity

Weitere Informationen finden Sie Identity unter:

Identity Komponenten

Alle abhängigen IdentityNuGet Pakete sind im ASP.NET Core freigegebenen Framework enthalten.

Das primäre Paket für IdentityMicrosoft.AspNetCore.Identity. Dieses Paket enthält den Kernsatz von Schnittstellen für ASP.NET Core Identity, und wird von Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migrieren zu ASP.NET Core Identity

Weitere Informationen und Anleitungen zum Migrieren Ihres vorhandenen Identity Speichers finden Sie unter Migrieren der Authentifizierung und Identity.

Festlegen der Kennwortstärke

Siehe Konfiguration für ein Beispiel, das die Mindestkennwortanforderungen festlegt.

AddDefaultIdentity und AddIdentity

AddDefaultIdentitywurde in ASP.NET Core 2.1 eingeführt. Der Anruf ähnelt dem Aufrufen AddDefaultIdentity der folgenden Schritte:

Weitere Informationen finden Sie in der AddDefault-QuelleIdentity.

Verhindern der Veröffentlichung statischer Identity Ressourcen

Um zu verhindern, dass statische Identity Ressourcen (Stylesheets und JavaScript-Dateien für die Benutzeroberfläche) zum Identity Webstamm veröffentlicht werden, fügen Sie die folgende ResolveStaticWebAssetsInputsDependsOn Eigenschaft und RemoveIdentityAssets ziel der Projektdatei der App hinzu:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Nächste Schritte