Dela via


Introduktion till Identity på ASP.NET Core

Av Rick Anderson

ASP.NET Core Identity:

  • Är ett API som stöder inloggningsfunktioner för användargränssnitt (UI).
  • Hanterar användare, lösenord, profildata, roller, anspråk, token, e-postbekräftelse med mera.

Användare kan skapa ett konto med inloggningsinformationen som lagras i Identity eller använda en extern inloggningsprovider. Externa inloggningsleverantörer som stöds är Facebook, Google, Microsoft-konto och Twitter-.

Information om hur du globalt kräver att alla användare autentiseras finns i Kräv autentiserade användare.

Den Identity källkoden finns på GitHub. Scaffold Identity och visa de genererade filerna för att granska mallinteraktionen med Identity.

Identity konfigureras vanligtvis med hjälp av en SQL Server-databas för att lagra användarnamn, lösenord och profildata. Du kan också använda en annan beständig lagringsplats, till exempel Azure Table Storage.

I det här avsnittet får du lära dig hur du använder Identity för att registrera, logga in och logga ut en användare. Obs! Mallarna behandlar användarnamn och e-post som samma för användare. Mer detaljerade anvisningar om hur du skapar appar som använder Identityfinns i Nästa steg.

ASP.NET Core Identity är inte relaterat till Microsofts identitetsplattform. Microsofts identitetsplattform är:

  • En utveckling av Utvecklarplattformen för Azure Active Directory (Azure AD).
  • En alternativ identitetslösning för autentisering och auktorisering i ASP.NET Core-appar.

ASP.NET Core Identity lägger till inloggningsfunktioner för användargränssnitt (UI) i ASP.NET Core-webbappar. Om du vill skydda webb-API:er och SPA:er använder du något av följande:

Duende Identity Server är ett OpenID Connect- och OAuth 2.0-ramverk för ASP.NET Core. Duende Identity Server aktiverar följande säkerhetsfunktioner:

  • Autentisering som en tjänst (AaaS)
  • Enkel inloggning/av(SSO) över flera programtyper
  • Åtkomstkontroll för API:er
  • Federationsgateway

Viktig

Duende Software kan kräva att du betalar en licensavgift för produktionsanvändning av Duende Identity Server. Mer information finns i Migrera från ASP.NET Core 5.0 till 6.0.

Mer information finns i Duende Identity Server-dokumentationen (Duende Software-webbplatsen).

Visa eller ladda ned exempelkoden (hur du laddar ned).

Skapa en webbapp med autentisering

Skapa ett ASP.NET Core Web Application-projekt med enskilda användarkonton.

  • Välj mallen ASP.NET Core Web App. Ge projektet namnet WebApp1 att ha samma namnområde som projektnedladdningen. Klicka på OK.
  • För indata för -autentiseringstyp, välj enskilda användarkonton.

Det genererade projektet tillhandahåller ASP.NET Core Identity som ett Razor klassbibliotek. Identity Razor-klassbiblioteket exponerar endpunkter i Identity-området. Till exempel:

  • /Identity/Konto/Logga in
  • /Identity/Account/Logga ut
  • /Identity/Konto/Hantera

Tillämpa migreringar

Använd migreringarna för att initiera databasen.

Kör följande kommando i Package Manager Console (PMC):

Update-Database

Testa registrering och inloggning

Kör appen och registrera en användare. Beroende på skärmstorleken kan du behöva välja navigeringsknappen för att se länkarna Registrera och Inloggning.

Visa Identity-databasen

  • På menyn Visa väljer du SQL Server Object Explorer (SSOX).
  • Gå till (localdb)MSSQLLocalDB(SQL Server 13). Högerklicka på dbo.AspNetUsers>Visa data:

snabbmeny i tabellen AspNetUsers i SQL Server Object Explorer

Konfigurera Identity tjänster

Tjänster läggs till i Program.cs. Det vanliga mönstret är att anropa metoder i följande ordning:

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

Föregående kod konfigurerar Identity med standardalternativvärden. Tjänster tillhandahålls till appen via beroendeinjektion.

Identity aktiveras genom att anropa UseAuthentication. UseAuthentication lägger till autentisering mellanprogram i pipelinen för begäran.

Den mallgenererade appen använder inte auktorisering. app.UseAuthorization ingår för att säkerställa att det läggs till i rätt ordning om appen lägger till auktorisering. UseRouting, UseAuthenticationoch UseAuthorization måste anropas i den ordning som visas i föregående kod.

Mer information om IdentityOptionsfinns i IdentityOptions och Application Startup.

Scaffold Registrera, Logga in, Logga ut och Registreringsbekräftelse

Lägg till filerna Register, Login, LogOutoch RegisterConfirmation. Följ Scaffold-identiteten till ett Razor-projekt med instruktioner för auktorisering för att generera koden som visas i det här avsnittet.

Granska register

När en användare klickar på knappen Registrera på sidan Register anropas åtgärden RegisterModel.OnPostAsync. Användaren skapas av CreateAsync(TUser)_userManager-objektet:

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

Inaktivera standardverifiering av konto

Med standardmallarna omdirigeras användaren till Account.RegisterConfirmation där de kan välja en länk för att få kontot bekräftat. Standard Account.RegisterConfirmation används endast för testning; automatisk kontoverifiering bör inaktiveras i en produktionsapp.

Om du vill kräva ett bekräftat konto och förhindra omedelbar inloggning vid registreringen anger du DisplayConfirmAccountLink = false i /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

Logga in

Inloggningsformuläret visas när:

  • Länken Logga in är markerad.
  • En användare försöker komma åt en begränsad sida som de inte har behörighet att komma åt eller när de inte har autentiserats av systemet.

När formuläret på inloggningssidan skickas anropas åtgärden OnPostAsync. PasswordSignInAsync anropas för objektet _signInManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

Information om hur du fattar auktoriseringsbeslut finns i Introduktion till auktorisering i ASP.NET Core.

Logga ut

Länken Logga ut anropar åtgärden LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

I föregående kod måste koden return RedirectToPage(); vara en omdirigering så att webbläsaren utför en ny begäran och identiteten för användaren uppdateras.

SignOutAsync raderar användarens lagrade anspråk i en cookie.

Posten anges i 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

Standardmallarna för webbprojekt tillåter anonym åtkomst till startsidorna. Om du vill testa Identitylägger du till [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()
        {
        }
    }
}

Logga ut om du är inloggad. Kör appen och välj länken Privacy. Du omdirigeras till inloggningssidan.

Utforska Identity

Så här utforskar du Identity mer detaljerat:

Identity-komponenter

Alla Identity-beroende NuGet-paket ingår i det delade ASP.NET Core-ramverket.

Det primära paketet för Identity är Microsoft.AspNetCore.Identity. Det här paketet innehåller kärnuppsättningen med gränssnitt för ASP.NET Core Identityoch ingår i Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migrera till ASP.NET Core Identity

Mer information och vägledning om hur du migrerar din befintliga Identity store finns i Migrera autentisering och Identity.

Ange lösenordsstyrka

Se Configuration för ett exempel som anger minimikraven för lösenord.

AddDefaultIdentity och AddIdentity

AddDefaultIdentity introducerades i ASP.NET Core 2.1. Att anropa AddDefaultIdentity liknar att anropa följande:

Mer information finns i AddDefaultIdentity-källa.

Förhindra publicering av statiska Identity tillgångar

Om du vill förhindra att statiska Identity-resurser (formatmallar och JavaScript-filer för Identity-användargränssnitt) publiceras till webbrot, lägg till följande ResolveStaticWebAssetsInputsDependsOn-egenskap och RemoveIdentityAssets-målfil i appens projektfil.

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

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

Nästa steg

Av Rick Anderson

ASP.NET Core Identity:

  • Är ett API som stöder inloggningsfunktioner för användargränssnitt (UI).
  • Hanterar användare, lösenord, profildata, roller, anspråk, token, e-postbekräftelse med mera.

Användare kan skapa ett konto med inloggningsinformationen som lagras i Identity eller använda en extern inloggningsprovider. Externa inloggningsleverantörer som stöds är Facebook, Google, Microsoft-konto och Twitter-.

Information om hur du globalt kräver att alla användare autentiseras finns i Kräv autentiserade användare.

Den Identity källkoden finns på GitHub. Scaffold Identity och visa de genererade filerna för att granska mallinteraktionen med Identity.

Identity konfigureras vanligtvis med hjälp av en SQL Server-databas för att lagra användarnamn, lösenord och profildata. Du kan också använda en annan beständig lagringsplats, till exempel Azure Table Storage.

I det här avsnittet får du lära dig hur du använder Identity för att registrera, logga in och logga ut en användare. Obs! Mallarna behandlar användarnamn och e-post som samma för användare. Mer detaljerade anvisningar om hur du skapar appar som använder Identityfinns i Nästa steg.

Microsofts identitetsplattform är:

  • En utveckling av Utvecklarplattformen för Azure Active Directory (Azure AD).
  • En alternativ identitetslösning för autentisering och auktorisering i ASP.NET Core-appar.
  • Inte relaterat till ASP.NET Core Identity.

ASP.NET Core Identity lägger till inloggningsfunktioner för användargränssnitt (UI) i ASP.NET Core-webbappar. Om du vill skydda webb-API:er och SPA:er använder du något av följande:

Duende IdentityServer är ett OpenID Connect- och OAuth 2.0-ramverk för ASP.NET Core. Duende IdentityServer aktiverar följande säkerhetsfunktioner:

  • Autentisering som en tjänst (AaaS)
  • Enkel inloggning/av(SSO) över flera programtyper
  • Åtkomstkontroll för API:er
  • Federationsgateway

Mer information finns i Översikt över Duende IdentityServer.

Mer information om andra autentiseringsprovidrar finns i Community OSS-autentiseringsalternativ för ASP.NET Core

Visa eller ladda ned exempelkoden (hur du laddar ned).

Skapa en webbapp med autentisering

Skapa ett ASP.NET Core Web Application-projekt med enskilda användarkonton.

  • Välj Fil>Nytt>Projekt.
  • Välj ASP.NET Core Web Application. Ge projektet namnet WebApp1 att ha samma namnområde som projektnedladdningen. Klicka på OK.
  • Välj en ASP.NET Core Web Applicationoch välj sedan Ändra autentisering.
  • Välj Enskilda Användarkonton och klicka på OK.

Det genererade projektet tillhandahåller ASP.NET Core Identity som ett Razor klassbibliotek. Identity Razor-klassbiblioteket exponerar slutpunkter med Identity-området. Till exempel:

  • /Identity/Konton/LoggaIn
  • /Identity/Konto/Logga ut
  • /Identity/Account/Manage

Utför migreringar

Använd migreringarna för att initiera databasen.

Kör följande kommando i Package Manager Console (PMC):

PM> Update-Database

Testa registrering och inloggning

Kör appen och registrera en användare. Beroende på skärmstorleken kan du behöva välja navigeringsknappen för att se länkarna Registrera och Inloggning.

Visa Identity-databasen

  • På menyn Visa väljer du SQL Server Object Explorer (SSOX).
  • Gå till (localdb)MSSQLLocalDB(SQL Server 13). Högerklicka på dbo.AspNetUsers>Visa data:

snabbmeny i tabellen AspNetUsers i SQL Server Object Explorer

Konfigurera Identity tjänster

Tjänster läggs till i ConfigureServices. Det vanliga mönstret är att anropa alla Add{Service} metoder och sedan anropa alla services.Configure{Service} metoder.

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

Föregående markerade kod konfigurerar Identity med standardalternativvärden. Tjänster görs tillgängliga för appen via beroendeinjektion.

Identity aktiveras genom att anropa UseAuthentication. UseAuthentication lägger till autentisering middleware i begärans pipeline.

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

Föregående kod konfigurerar Identity med standardalternativvärden. Tjänster görs tillgängliga för appen via beroendeinjektion.

Identity aktiveras genom att anropa UseAuthentication. UseAuthentication lägger till autentiserings-mellanprogramvara i begärans pipeline.

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

Den mallgenererade appen använder inte auktorisering. app.UseAuthorization ingår för att säkerställa att det läggs till i rätt ordning om appen lägger till auktorisering. UseRouting, UseAuthentication, UseAuthorizationoch UseEndpoints måste anropas i den ordning som visas i föregående kod.

Mer information om IdentityOptions och Startupfinns i IdentityOptions och Application Startup.

Skapa mall för registrering, inloggning, utloggning och registreringsbekräftelse

Lägg till filerna Register, Login, LogOutoch RegisterConfirmation. Följ scaffold-identiteten i ett Razor-projekt med auktoriseringsinstruktioner för att generera koden som visas i det här avsnittet.

Granska registret

När en användare klickar på knappen Registrera på sidan Register anropas åtgärden RegisterModel.OnPostAsync. Användaren skapas av CreateAsync(TUser)_userManager-objektet:

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

Inaktivera standardverifiering av konto

Med standardmallarna omdirigeras användaren till Account.RegisterConfirmation där de kan välja en länk för att få kontot bekräftat. Standard Account.RegisterConfirmation används endast för testning. Automatisk kontoverifiering ska inaktiveras i en produktionsapp.

Om du vill kräva ett bekräftat konto och förhindra omedelbar inloggning vid registreringen anger du DisplayConfirmAccountLink = false i /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

Logga in

Inloggningsformuläret visas när:

  • Länken Logga in är markerad.
  • En användare försöker komma åt en begränsad sida som de inte har behörighet att komma åt eller när de inte har autentiserats av systemet.

När formuläret på inloggningssidan skickas anropas åtgärden OnPostAsync. PasswordSignInAsync anropas för objektet _signInManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

Information om hur du fattar auktoriseringsbeslut finns i Introduktion till auktorisering i ASP.NET Core.

Logga ut

Länken Logga ut anropar åtgärden LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

I föregående kod måste koden return RedirectToPage(); vara en omdirigering så att webbläsaren utför en ny begäran och identiteten för användaren uppdateras.

SignOutAsync raderar anspråk som användaren lagrar i en cookie.

Posten anges i fält 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>

Testa Identity

Standardmallarna för webbprojekt tillåter anonym åtkomst till startsidorna. Om du vill testa Identitylägger du till [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()
        {
        }
    }
}

Logga ut om du är inloggad. Kör appen och välj länken Privacy. Du omdirigeras till inloggningssidan.

Utforska Identity

Så här utforskar du Identity mer detaljerat:

Identity-komponenter

Alla Identity-beroende NuGet-paket ingår i det delade ASP.NET Core-ramverket.

Det primära paketet för Identity är Microsoft.AspNetCore.Identity. Det här paketet innehåller kärnuppsättningen med gränssnitt för ASP.NET Core Identityoch ingår i Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migrera till ASP.NET Core Identity

Mer information och vägledning om hur du migrerar din befintliga Identity store finns i Migrera autentisering och Identity.

Ange lösenordsstyrka

Se Configuration för ett exempel som anger minimikraven för lösenord.

Förhindra publicering av statiska Identity tillgångar

Om du vill förhindra att statiska Identity-resurser (formatmallar och JavaScript-filer för Identity användargränssnitt) publiceras till webbrot, lägger du till följande ResolveStaticWebAssetsInputsDependsOn-egenskap och RemoveIdentityAssets-mål i appens projektfil:

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

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

Nästa steg