Delen via


Inleiding tot Identity op ASP.NET Core

Door Rick Anderson

ASP.NET Core-Identity:

  • Is een API die aanmeldingsfunctionaliteit van de gebruikersinterface (UI) ondersteunt.
  • Beheert gebruikers, wachtwoorden, profielgegevens, rollen, claims, tokens, e-mailbevestiging en meer.

Gebruikers kunnen een account maken met de aanmeldingsgegevens die zijn opgeslagen in Identity of ze kunnen een externe aanmeldingsprovider gebruiken. Ondersteunde externe aanmeldingsproviders zijn Facebook, Google, Microsoft-account en Twitter-.

Zie Geverifieerde gebruikers vereisenvoor informatie over het globaal vereisen van verificatie van alle gebruikers.

De Identity broncode is beschikbaar op GitHub. Scaffold Identity en bekijk de gegenereerde bestanden om de interactie met sjabloon Identityte beoordelen.

Identity wordt doorgaans geconfigureerd met behulp van een SQL Server-database voor het opslaan van gebruikersnamen, wachtwoorden en profielgegevens. U kunt ook een ander permanent archief gebruiken, bijvoorbeeld Azure Table Storage.

In dit onderwerp leert u hoe u Identity kunt gebruiken om een gebruiker te registreren, aan te melden en af te melden. Opmerking: de sjablonen behandelen gebruikersnaam en e-mail als dezelfde voor gebruikers. Zie Volgende stappenvoor meer gedetailleerde instructies over het maken van apps die gebruikmaken van Identity.

ASP.NET Core Identity is niet gerelateerd aan het Microsoft Identity Platform. Microsoft Identity Platform is:

  • Een evolutie van het Azure Ad-ontwikkelaarsplatform (Azure Active Directory).
  • Een alternatieve identiteitsoplossing voor verificatie en autorisatie in ASP.NET Core-apps.

ASP.NET Core Identity voegt de aanmeldingsfunctionaliteit van de gebruikersinterface (UI) toe aan ASP.NET Core-web-apps. Gebruik een van de volgende manieren om web-API's en SPA's te beveiligen:

Duende Identity Server is een OpenID Connect- en OAuth 2.0-framework voor ASP.NET Core. Duende Identity Server maakt de volgende beveiligingsfuncties mogelijk:

  • Verificatie als een service (AaaS)
  • Eenmalige aanmelding/uit (SSO) voor meerdere toepassingstypen
  • Toegangsbeheer voor API's
  • Federatieve gateway

Belangrijk

Duende Software moet u mogelijk een licentiekosten betalen voor productiegebruik van Duende Identity Server. Zie Migreren van ASP.NET Core 5.0 naar 6.0voor meer informatie.

Zie de Duende Identity Server-documentatie (Duende Software-website)voor meer informatie.

De voorbeeldcode bekijken of downloaden (hoe te downloaden).

Een web-app maken met verificatie

Maak een ASP.NET Core Web Application-project met afzonderlijke gebruikersaccounts.

  • Selecteer de sjabloon ASP.NET Core Web App. Geef het project WebApp1 de naam zodat het dezelfde naamruimte heeft als de project download. Klik op OK-.
  • Selecteer in het verificatietype invoer afzonderlijke gebruikersaccounts.

Het gegenereerde project biedt ASP.NET Core Identity als een Razor class library. De IdentityRazor classbibliotheek biedt toegang tot eindpunten binnen het Identity gebied. Bijvoorbeeld:

  • /Identity/Account/Aanmelding
  • /Identity/Account/Uitloggen
  • /Identity/Account/Beheren

Migraties toepassen

Pas de migraties toe voor het initialiseren van de database.

Voer de volgende opdracht uit in de Package Manager Console (PMC):

Update-Database

Registratie en inloggen testen

Voer de app uit en registreer een gebruiker. Afhankelijk van de schermgrootte moet u mogelijk de navigatie-wisselknop selecteren om de koppelingen Registreren en Inloggen te zien.

De Identity-database weergeven

  • Vanuit het menu Weergave selecteer SQL Server Object Explorer (SSOX).
  • Navigeer naar (localdb)MSSQLLocalDB(SQL Server 13). Klik met de rechtermuisknop op dbo. AspNetUsers>Gegevens weergeven:

Contextmenu in de tabel AspNetUsers in SQL Server Object Explorer

Identity-services configureren

Services worden toegevoegd in Program.cs. Het gebruikelijke patroon is het aanroepen van methoden in de volgende volgorde:

  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();

De voorgaande code configureert Identity met standaardoptiewaarden. Services worden beschikbaar gemaakt voor de app via afhankelijkheidsinjectie.

Identity is ingeschakeld door UseAuthenticationaan te roepen. UseAuthentication voegt verificatie-middleware- toe aan de aanvraagpijplijn.

De door de sjabloon gegenereerde app maakt geen gebruik van autorisatie. app.UseAuthorization is opgenomen om ervoor te zorgen dat deze in de juiste volgorde wordt toegevoegd als de app autorisatie toevoegt. UseRouting, UseAuthenticationen UseAuthorization moeten worden aangeroepen in de volgorde die in de voorgaande code wordt weergegeven.

Zie IdentityOptions en Application Startupvoor meer informatie over IdentityOptions.

Scaffold Registreren, Inloggen, Uitloggen en Registratiebevestiging

Voeg de bestanden Register, Login, LogOuten RegisterConfirmation toe. Volg de Scaffold identiteit naar een Razor-project met autorisatie-instructies voor het genereren van code zoals in deze sectie weergegeven.

Register onderzoeken

Wanneer een gebruiker op de knop Registreren op de pagina Register klikt, wordt de actie RegisterModel.OnPostAsync aangeroepen. De gebruiker wordt gemaakt door CreateAsync(TUser) op het _userManager-object:

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();
}

Standaardaccountverificatie uitschakelen

Met de standaardsjablonen wordt de gebruiker omgeleid naar de Account.RegisterConfirmation waar ze een koppeling kunnen selecteren om het account te laten bevestigen. De standaard Account.RegisterConfirmation wordt gebruikt alleen voor testen. Automatische accountverificatie moet worden uitgeschakeld in een productie-app.

Als u een bevestigd account wilt vereisen en onmiddellijke aanmelding bij de registratie wilt voorkomen, stelt u DisplayConfirmAccountLink = false in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.csin:

[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();
    }
}

Aanmelden

Het aanmeldingsformulier wordt weergegeven wanneer:

  • De Aanmelden koppeling is geselecteerd.
  • Een gebruiker probeert toegang te krijgen tot een beperkte pagina waar ze geen toestemming voor hebben, of, wanneer ze niet door het systeem zijn geverifieerd.

Wanneer het formulier op de aanmeldingspagina wordt verzonden, wordt de actie OnPostAsync aangeroepen. PasswordSignInAsync wordt aangeroepen op het _signInManager-object.

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();
}

Zie Inleiding tot autorisatie in ASP.NET Corevoor meer informatie over het nemen van autorisatiebeslissingen.

Uitloggen

De afmelden koppeling roept de actie LogoutModel.OnPost aan.

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();
            }
        }
    }
}

In de voorgaande code moet de code return RedirectToPage(); een omleiding zijn, zodat de browser een nieuwe aanvraag uitvoert en de identiteit voor de gebruiker wordt bijgewerkt.

SignOutAsync wist de claims van de gebruiker die zijn opgeslagen in een cookie.

Post is opgegeven in de 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

Met de standaardwebprojectsjablonen is anonieme toegang tot de startpagina's toegestaan. Als u Identitywilt testen, voegt u [Authorize]toe:

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()
        {
        }
    }
}

Als u bent aangemeld, meldt u zich af. Voer de app uit en selecteer de koppeling Privacy. U wordt omgeleid naar de aanmeldingspagina.

Verken Identity

Meer informatie over Identity:

Identity-onderdelen

Alle Identity-afhankelijke NuGet-pakketten zijn opgenomen in het ASP.NET Core-gedeelde framework.

Het primaire pakket voor Identity is Microsoft.AspNetCore.Identity. Dit pakket bevat de kernset interfaces voor ASP.NET Core Identityen is opgenomen in Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migreren naar ASP.NET Core-Identity

Voor meer informatie en richtlijnen over het migreren van uw bestaande Identity winkel, zie Verificatie migreren en Identity.

Wachtwoordsterkte instellen

Zie Configuration voor een voorbeeld waarmee de minimale wachtwoordvereisten worden ingesteld.

AddDefaultIdentity en AddIdentity

AddDefaultIdentity werd geïntroduceerd in ASP.NET Core 2.1. Bellen AddDefaultIdentity is vergelijkbaar met het aanroepen van het volgende:

Zie AddDefaultIdentity-bron voor meer informatie.

Publicatie van statische Identity assets voorkomen

Om te voorkomen dat statische Identity assets (opmaakmodellen en JavaScript-bestanden voor Identity gebruikersinterface) naar de webroot worden gepubliceerd, voeg de volgende ResolveStaticWebAssetsInputsDependsOn eigenschap en RemoveIdentityAssets doel toe aan het projectbestand van de app:

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

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

Volgende stappen

Door Rick Anderson

ASP.NET Core-Identity:

  • Is een API die aanmeldingsfunctionaliteit van de gebruikersinterface (UI) ondersteunt.
  • Beheert gebruikers, wachtwoorden, profielgegevens, rollen, claims, tokens, e-mailbevestiging en meer.

Gebruikers kunnen een account maken met de aanmeldingsgegevens die zijn opgeslagen in Identity of ze kunnen een externe aanmeldingsprovider gebruiken. Ondersteunde externe aanmeldingsproviders zijn Facebook, Google, Microsoft-account en Twitter-.

Zie Geverifieerde gebruikers vereisenvoor informatie over het globaal vereisen van verificatie van alle gebruikers.

De Identity broncode is beschikbaar op GitHub. Scaffold Identity en bekijk de gegenereerde bestanden om de interactie van de sjabloon met Identityte controleren.

Identity wordt doorgaans geconfigureerd met behulp van een SQL Server-database voor het opslaan van gebruikersnamen, wachtwoorden en profielgegevens. U kunt ook een ander permanent archief gebruiken, bijvoorbeeld Azure Table Storage.

In dit onderwerp leert u hoe u Identity kunt gebruiken om een gebruiker te registreren, aan te melden en af te melden. Opmerking: de sjablonen behandelen gebruikersnaam en e-mail als dezelfde voor gebruikers. Zie Volgende stappenvoor meer gedetailleerde instructies over het maken van apps die gebruikmaken van Identity.

Microsoft Identity Platform is:

  • Een evolutie van het Azure Ad-ontwikkelaarsplatform (Azure Active Directory).
  • Een alternatieve identiteitsoplossing voor verificatie en autorisatie in ASP.NET Core-apps.
  • Niet gerelateerd aan ASP.NET Core Identity.

ASP.NET Core Identity voegt de aanmeldingsfunctionaliteit van de gebruikersinterface (UI) toe aan ASP.NET Core-web-apps. Gebruik een van de volgende manieren om web-API's en SPA's te beveiligen:

Duende IdentityServer is een OpenID Connect- en OAuth 2.0-framework voor ASP.NET Core. Duende IdentityServer maakt de volgende beveiligingsfuncties mogelijk:

  • Verificatie als een service (AaaS)
  • Eenmalige aanmelding/uit (SSO) voor meerdere toepassingstypen
  • Toegangsbeheer voor API's
  • Federatieve gateway

Zie Overzicht van Duende IdentityServervoor meer informatie.

Raadpleeg Community OSS-verificatieopties voor ASP.NET Core voor meer informatie over andere authenticatieproviders.

De voorbeeldcode bekijken of downloaden (hoe te downloaden).

Een web-app maken met verificatie

Maak een ASP.NET Core Web Application-project met afzonderlijke gebruikersaccounts.

  • Selecteer Bestand>Nieuw>Project.
  • Selecteer ASP.NET Core Web Application. Geef het project WebApp1 dezelfde naamruimte als de namespace van de projectdownload. Klik op OK-.
  • Selecteer een ASP.NET Core Web Applicationen selecteer vervolgens Verificatie wijzigen.
  • Selecteer afzonderlijke gebruikersaccounts en klik op OK.

Het gegenereerde project biedt ASP.NET Core Identity als een Razor class library. De IdentityRazor classbibliotheek ontsluit eindpunten binnen het Identity domein. Bijvoorbeeld:

  • /Identity/Account/Aanmelding
  • /Identity/Account/Uitloggen
  • /Identity/Account/Beheren

Migraties toepassen

Pas de migraties toe om de database te initialiseren.

Voer de volgende opdracht uit in de Package Manager Console (PMC):

PM> Update-Database

Registreren en aanmelden testen

Voer de app uit en registreer een gebruiker. Afhankelijk van de schermgrootte moet u mogelijk de navigatiewisselknop selecteren om de Registreren en Inloggen koppelingen te zien.

De Identity-database weergeven

  • In het menu Weergave, selecteer SQL Server Object Explorer (SSOX).
  • Navigeer naar (localdb)MSSQLLocalDB(SQL Server 13). Klik met de rechtermuisknop op dbo. AspNetUsers>Gegevens weergeven:

contextmenu van de tabel AspNetUsers in SQL Server Object Explorer

De Identity-services configureren

Diensten worden toegevoegd in ConfigureServices. Het typische patroon is om alle Add{Service} methoden aan te roepen en vervolgens alle services.Configure{Service} methoden aan te roepen.

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;
    });
}

De voorgaande gemarkeerde code configureert Identity met standaardoptiewaarden. Diensten worden via afhankelijkheidsinjectieaan de app beschikbaar gesteld.

Identity is ingeschakeld door UseAuthenticationaan te roepen. UseAuthentication voegt de middleware voor authenticatie toe aan de aanvraagpijplijn.

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;
    });
}

De voorgaande code configureert Identity met standaardoptiewaarden. De app krijgt toegang tot services via afhankelijkheidsinjectie.

Identity is ingeschakeld door UseAuthenticationaan te roepen. UseAuthentication voegt authenticatie middleware toe aan de aanvraagpijplijn.

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();
    });
}

De door de sjabloon gegenereerde app maakt geen gebruik van autorisatie. app.UseAuthorization is opgenomen om ervoor te zorgen dat deze in de juiste volgorde wordt toegevoegd als de app autorisatie toevoegt. UseRouting, UseAuthentication, UseAuthorizationen UseEndpoints moeten worden aangeroepen in de volgorde die in de voorgaande code wordt weergegeven.

Zie IdentityOptions en Application Startupvoor meer informatie over IdentityOptions en Startup.

Stel Registreer, Inloggen, Uitloggen en Registratiebevestiging op

Voeg de bestanden Register, Login, LogOuten RegisterConfirmation toe. Volg de Scaffold-identiteit in een Razor project met autorisatie instructies voor het genereren van de code die in deze sectie wordt weergegeven.

Register onderzoeken

Wanneer een gebruiker op de knop Registreren op de pagina Register klikt, wordt de actie RegisterModel.OnPostAsync aangeroepen. De gebruiker wordt gemaakt door CreateAsync(TUser) op het _userManager-object:

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();
}

Verificatie van standaardaccount uitschakelen

Met de standaardsjablonen wordt de gebruiker omgeleid naar de Account.RegisterConfirmation waar ze een koppeling kunnen selecteren om het account te laten bevestigen. De standaard Account.RegisterConfirmation wordt gebruikt alleen voor testen, automatische accountverificatie moet worden uitgeschakeld in een productieapplicatie.

Als u een bevestigd account wilt vereisen en onmiddellijke aanmelding bij de registratie wilt voorkomen, stelt u DisplayConfirmAccountLink = false in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.csin:

[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();
    }
}

Aanmelden

Het aanmeldingsformulier wordt weergegeven wanneer:

  • De link Inloggen bij is geselecteerd.
  • Een gebruiker probeert toegang te krijgen tot een beperkte pagina, of, waarvoor hij/zij geen toestemming heeft, wanneer hij/zij niet door het systeem is geverifieerd.

Wanneer het formulier op de aanmeldingspagina wordt verzonden, wordt de actie OnPostAsync aangeroepen. PasswordSignInAsync wordt aangeroepen op het _signInManager-object.

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();
}

Zie Inleiding tot autorisatie in ASP.NET Corevoor meer informatie over het nemen van autorisatiebeslissingen.

Uitloggen

De afmelden koppeling roept de actie LogoutModel.OnPost aan.

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();
            }
        }
    }
}

In de voorgaande code moet de code return RedirectToPage(); een omleiding zijn, zodat de browser een nieuwe aanvraag uitvoert en de identiteit voor de gebruiker wordt bijgewerkt.

SignOutAsync wist de claims van de gebruiker die zijn opgeslagen in een cookie.

Post is opgegeven in de 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

Met de standaardwebprojectsjablonen is anonieme toegang tot de startpagina's toegestaan. Als u Identitywilt testen, voegt u [Authorize]toe:

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()
        {
        }
    }
}

Als u bent aangemeld, meldt u zich af. Voer de app uit en selecteer de koppeling Privacy. U wordt omgeleid naar de aanmeldingspagina.

Verken Identity

Meer informatie over Identity:

Identity-onderdelen

Alle Identity-afhankelijke NuGet-pakketten zijn opgenomen in het ASP.NET Core-gedeelde framework.

Het primaire pakket voor Identity is Microsoft.AspNetCore.Identity. Dit pakket bevat de kernset interfaces voor ASP.NET Core Identityen is opgenomen in Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migreren naar ASP.NET Core-Identity

Voor meer informatie en richtlijnen over het migreren van uw bestaande Identity winkel, zie Migratie van authenticatie en Identity.

Wachtwoordsterkte instellen

Zie Configuration voor een voorbeeld waarmee de minimale wachtwoordvereisten worden ingesteld.

Voorkom de publicatie van statische Identity assets

Als u wilt voorkomen dat statische Identity assets (opmaakmodellen en JavaScript-bestanden voor Identity gebruikersinterface) worden gepubliceerd naar de web-root, voegt u de volgende ResolveStaticWebAssetsInputsDependsOn eigenschap en RemoveIdentityAssets target toe aan het projectbestand van de app.

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

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

Volgende stappen