Wprowadzenie do Identity ASP.NET Core

Autor: Rick Anderson

ASP.NET Core Identity:

  • To interfejs API, który obsługuje funkcje logowania interfejsu użytkownika.
  • Zarządza użytkownikami, hasłami, danymi profilu, rolami, oświadczeniami, tokenami, potwierdzeniem wiadomości e-mail i nie tylko.

Użytkownicy mogą utworzyć konto przy użyciu informacji logowania przechowywanych w Identity programie lub użyć zewnętrznego dostawcy logowania. Obsługiwani zewnętrzni dostawcy logowania to Facebook , Google, Konto Microsoft i Twitter.

Aby uzyskać informacje na temat globalnego wymagania uwierzytelnienia wszystkich użytkowników, zobacz Wymaganie uwierzytelnionych użytkowników.

Kod Identity źródłowy jest dostępny w witrynie GitHub. Identity Tworzenie szkieletu i wyświetlanie wygenerowanych plików w celu przejrzenia interakcji szablonu z Identityprogramem .

Identity Program jest zwykle konfigurowany przy użyciu bazy danych programu SQL Server do przechowywania nazw użytkowników, haseł i danych profilu. Alternatywnie można użyć innego magazynu trwałego, na przykład usługi Azure Table Storage.

W tym temacie dowiesz się, jak zarejestrować, zalogować się i wylogować Identity użytkownika. Uwaga: szablony traktują nazwę użytkownika i adres e-mail jako taki sam dla użytkowników. Aby uzyskać bardziej szczegółowe instrukcje dotyczące tworzenia aplikacji korzystających z usługi Identity, zobacz Następne kroki.

ASP.NET Core Identity nie jest powiązany z Platforma tożsamości Microsoft. Platforma tożsamości Microsoft to:

  • Ewolucja platformy deweloperów usługi Azure Active Directory (Azure AD).
  • Alternatywne rozwiązanie do obsługi tożsamości na potrzeby uwierzytelniania i autoryzacji w aplikacjach platformy ASP.NET Core.

ASP.NET Core Identity dodaje funkcje logowania interfejsu użytkownika do aplikacji internetowych platformy ASP.NET Core. Aby zabezpieczyć internetowe interfejsy API i spA, użyj jednego z następujących elementów:

Duende Identity Server to platforma OpenID Połączenie i OAuth 2.0 dla platformy ASP.NET Core. Serwer Duende Identity umożliwia korzystanie z następujących funkcji zabezpieczeń:

  • Uwierzytelnianie jako usługa (AaaS)
  • Logowanie jednokrotne/wyłączanie logowania jednokrotnego w wielu typach aplikacji
  • Kontrola dostępu dla interfejsów API
  • Brama federacyjna

Ważne

Oprogramowanie Duende może wymagać zapłacenia opłaty licencyjnej za korzystanie z serwera Duende Identity Server w środowisku produkcyjnym. Aby uzyskać więcej informacji, zobacz Migracja z platformy ASP.NET Core w wersji 5.0 do wersji 6.0.

Aby uzyskać więcej informacji, zobacz dokumentację serwera Duende (witryna internetowa Duende Identity Software).

Wyświetl lub pobierz przykładowy kod (jak pobrać).

Tworzenie aplikacji internetowej z uwierzytelnianiem

Utwórz projekt aplikacji internetowej platformy ASP.NET Core przy użyciu indywidualnych kont użytkowników.

  • Wybierz szablon aplikacji internetowej ASP.NET Core. Nadaj projektowi nazwę WebApp1 tak, aby miała taką samą przestrzeń nazw jak pobieranie projektu. Kliknij przycisk OK.
  • W polu danych wejściowych Typ uwierzytelniania wybierz pozycję Pojedyncze konta użytkowników.

Wygenerowany projekt udostępnia ASP.NET Core Identity jako bibliotekę Razorklas. Biblioteka IdentityRazor klas uwidacznia punkty końcowe w Identity obszarze. Na przykład:

  • /Identity/Konto/Logowanie
  • /Identity/Konto/Wylogowywanie
  • /Identity/Konto/Zarządzanie

Stosowanie migracji

Zastosuj migracje, aby zainicjować bazę danych.

Uruchom następujące polecenie w konsoli Menedżer pakietów (PMC):

Update-Database

Testowanie rejestracji i logowania

Uruchom aplikację i zarejestruj użytkownika. W zależności od rozmiaru ekranu może być konieczne wybranie przycisku przełącznika nawigacji, aby wyświetlić linki Zarejestruj i Zaloguj .

Identity Wyświetlanie bazy danych

  • Z menu Widok wybierz pozycję SQL Server Eksplorator obiektów (SSOX).
  • Przejdź do (localdb)MSSQLLocalDB(SQL Server 13). Kliknij prawym przyciskiem myszy pozycję dbo. Dane widoku aspNetUsers>:

Contextual menu on AspNetUsers table in SQL Server Object Explorer

Konfigurowanie Identity usług

Usługi są dodawane w programie Program.cs. Typowy wzorzec polega na wywołaniu metod w następującej kolejności:

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

Powyższy kod konfiguruje Identity z domyślnymi wartościami opcji. Usługi są udostępniane aplikacji za pośrednictwem wstrzykiwania zależności.

Identity jest włączona przez wywołanie metody UseAuthentication. UseAuthenticationDodaje oprogramowanie pośredniczące uwierzytelniania do potoku żądania.

Aplikacja wygenerowana przez szablon nie używa autoryzacji. app.UseAuthorization element jest uwzględniony, aby upewnić się, że jest dodawany w odpowiedniej kolejności, jeśli aplikacja doda autoryzację. UseRouting, UseAuthenticationi UseAuthorization musi być wywoływana w kolejności pokazanej w poprzednim kodzie.

Aby uzyskać więcej informacji na temat IdentityOptionsprogramu , zobacz IdentityOptions i Uruchamianie aplikacji.

Rejestrowanie szkieletu, logowanie, rejestrowanie i rejestrowanieKonfirmacja

RegisterDodaj pliki , Login, LogOuti RegisterConfirmation . Postępuj zgodnie z tożsamością szkieletu w Razor projekcie z instrukcjami autoryzacji , aby wygenerować kod pokazany w tej sekcji.

Sprawdzanie rejestru

Gdy użytkownik kliknie przycisk Zarejestruj na Register stronie, RegisterModel.OnPostAsync zostanie wywołana akcja. Użytkownik jest tworzony przez CreateAsync(TUser) użytkownika w _userManager obiekcie :

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

Wyłącz domyślną weryfikację konta

W przypadku szablonów domyślnych użytkownik jest przekierowywany do Account.RegisterConfirmation lokalizacji, w której może wybrać link, aby potwierdzić konto. Wartość domyślna Account.RegisterConfirmation jest używana tylko do testowania, automatyczna weryfikacja konta powinna być wyłączona w aplikacji produkcyjnej.

Aby wymagać potwierdzonego konta i zapobiec natychmiastowemu zalogowaniu podczas rejestracji, ustaw wartość w pliku DisplayConfirmAccountLink = false/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();
    }
}

Logowanie się

Formularz logowania jest wyświetlany, gdy:

  • Wybrano link Zaloguj .
  • Użytkownik próbuje uzyskać dostęp do strony z ograniczeniami, do której nie ma uprawnień dostępu lub gdy nie został uwierzytelniony przez system.

Po przesłaniu formularza na stronie Logowania akcja jest wywoływana OnPostAsync . PasswordSignInAsync element jest wywoływany _signInManager na obiekcie .

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

Aby uzyskać informacje na temat podejmowania decyzji dotyczących autoryzacji, zobacz Wprowadzenie do autoryzacji w programie ASP.NET Core.

Wyloguj się

Link WylogujLogoutModel.OnPost wywołuje akcję.

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

W poprzednim kodzie kod return RedirectToPage(); musi być przekierowaniem, aby przeglądarka wykonała nowe żądanie, a tożsamość użytkownika zostanie zaktualizowana.

SignOutAsync czyści oświadczenia użytkownika przechowywane w obiekcie cookie.

Wpis jest określony w pliku 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

Domyślne szablony projektów internetowych umożliwiają anonimowy dostęp do stron domowych. Aby przetestować Identitypolecenie , dodaj polecenie [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()
        {
        }
    }
}

Jeśli się zalogujesz, wyloguj się. Uruchom aplikację i wybierz Privacy link. Nastąpi przekierowanie do strony logowania.

Poznaj Identity

Aby zapoznać się Identity bardziej szczegółowo:

Identity Składniki

IdentityWszystkie pakiety NuGet zależne są zawarte w strukturze udostępnionej ASP.NET Core.

Podstawowym pakietem programu Identity jest Microsoft.AspNetCore.Identity. Ten pakiet zawiera podstawowy zestaw interfejsów dla ASP.NET Core Identityi jest uwzględniony przez Microsoft.AspNetCore.Identity.EntityFrameworkCoreprogram .

Migrowanie do platformy ASP.NET Core Identity

Aby uzyskać więcej informacji i wskazówek dotyczących migrowania istniejącego Identity magazynu, zobacz Migrowanie uwierzytelniania i Identity.

Ustawianie siły hasła

Zobacz Konfiguracja przykładu, który określa minimalne wymagania dotyczące hasła.

AddDefaultIdentity i AddIdentity

AddDefaultIdentity wprowadzono w ASP.NET Core 2.1. Wywołanie AddDefaultIdentity jest podobne do wywołania następującego:

Aby uzyskać więcej informacji, zobacz AddDefault source (Źródło addDefaultIdentity).

Zapobieganie publikowaniu zasobów statycznych Identity

Aby zapobiec publikowaniu statycznych Identity zasobów (arkuszy stylów i plików JavaScript dla Identity interfejsu użytkownika) w katalogu głównym sieci Web, dodaj następującą ResolveStaticWebAssetsInputsDependsOn właściwość i RemoveIdentityAssets element docelowy do pliku projektu aplikacji:

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

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

Następne kroki

Autor: Rick Anderson

ASP.NET Core Identity:

  • To interfejs API, który obsługuje funkcje logowania interfejsu użytkownika.
  • Zarządza użytkownikami, hasłami, danymi profilu, rolami, oświadczeniami, tokenami, potwierdzeniem wiadomości e-mail i nie tylko.

Użytkownicy mogą utworzyć konto przy użyciu informacji logowania przechowywanych w Identity programie lub użyć zewnętrznego dostawcy logowania. Obsługiwani zewnętrzni dostawcy logowania to Facebook , Google, Konto Microsoft i Twitter.

Aby uzyskać informacje na temat globalnego wymagania uwierzytelnienia wszystkich użytkowników, zobacz Wymaganie uwierzytelnionych użytkowników.

Kod Identity źródłowy jest dostępny w witrynie GitHub. Identity Tworzenie szkieletu i wyświetlanie wygenerowanych plików w celu przejrzenia interakcji szablonu z Identityprogramem .

Identity Program jest zwykle konfigurowany przy użyciu bazy danych programu SQL Server do przechowywania nazw użytkowników, haseł i danych profilu. Alternatywnie można użyć innego magazynu trwałego, na przykład usługi Azure Table Storage.

W tym temacie dowiesz się, jak zarejestrować, zalogować się i wylogować Identity użytkownika. Uwaga: szablony traktują nazwę użytkownika i adres e-mail jako taki sam dla użytkowników. Aby uzyskać bardziej szczegółowe instrukcje dotyczące tworzenia aplikacji korzystających z usługi Identity, zobacz Następne kroki.

Platforma tożsamości Microsoft to:

  • Ewolucja platformy deweloperów usługi Azure Active Directory (Azure AD).
  • Alternatywne rozwiązanie do obsługi tożsamości na potrzeby uwierzytelniania i autoryzacji w aplikacjach platformy ASP.NET Core.
  • Nie dotyczy ASP.NET Core Identity.

ASP.NET Core Identity dodaje funkcje logowania interfejsu użytkownika do aplikacji internetowych platformy ASP.NET Core. Aby zabezpieczyć internetowe interfejsy API i spA, użyj jednego z następujących elementów:

Duende IdentityServer to platforma OpenID Połączenie i OAuth 2.0 dla platformy ASP.NET Core. Serwer Duende Identityumożliwia korzystanie z następujących funkcji zabezpieczeń:

  • Uwierzytelnianie jako usługa (AaaS)
  • Logowanie jednokrotne/wyłączanie logowania jednokrotnego w wielu typach aplikacji
  • Kontrola dostępu dla interfejsów API
  • Brama federacyjna

Aby uzyskać więcej informacji, zobacz Omówienie serwera DuendeIdentity.

Aby uzyskać więcej informacji na temat innych dostawców uwierzytelniania, zobacz Community OSS authentication options for ASP.NET Core (Opcje uwierzytelniania systemu operacyjnego Community dla platformy ASP.NET Core)

Wyświetl lub pobierz przykładowy kod (jak pobrać).

Tworzenie aplikacji internetowej z uwierzytelnianiem

Utwórz projekt aplikacji internetowej platformy ASP.NET Core przy użyciu indywidualnych kont użytkowników.

  • Wybierz kolejno pozycje Plik>Nowy>Projekt.
  • Wybierz pozycję ASP.NET Core Web Application(Podstawowa aplikacja internetowa). Nadaj projektowi nazwę WebApp1 tak, aby miała taką samą przestrzeń nazw jak pobieranie projektu. Kliknij przycisk OK.
  • Wybierz aplikację internetową ASP.NET Core, a następnie wybierz pozycję Zmień uwierzytelnianie.
  • Wybierz pozycję Indywidualne konta użytkowników i kliknij przycisk OK.

Wygenerowany projekt udostępnia ASP.NET Core Identity jako bibliotekę Razorklas. Biblioteka IdentityRazor klas uwidacznia punkty końcowe w Identity obszarze. Na przykład:

  • /Identity/Konto/Logowanie
  • /Identity/Konto/Wylogowywanie
  • /Identity/Konto/Zarządzanie

Stosowanie migracji

Zastosuj migracje, aby zainicjować bazę danych.

Uruchom następujące polecenie w konsoli Menedżer pakietów (PMC):

PM> Update-Database

Testowanie rejestracji i logowania

Uruchom aplikację i zarejestruj użytkownika. W zależności od rozmiaru ekranu może być konieczne wybranie przycisku przełącznika nawigacji, aby wyświetlić linki Zarejestruj i Zaloguj .

Identity Wyświetlanie bazy danych

  • Z menu Widok wybierz pozycję SQL Server Eksplorator obiektów (SSOX).
  • Przejdź do (localdb)MSSQLLocalDB(SQL Server 13). Kliknij prawym przyciskiem myszy pozycję dbo. Dane widoku aspNetUsers>:

Contextual menu on AspNetUsers table in SQL Server Object Explorer

Konfigurowanie Identity usług

Usługi są dodawane w programie ConfigureServices. Typowy wzorzec polega na wywołaniu wszystkich Add{Service} metod, a następnie wywołaniu wszystkich services.Configure{Service} metod.

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

Powyższy wyróżniony kod konfiguruje Identity z domyślnymi wartościami opcji. Usługi są udostępniane aplikacji za pośrednictwem wstrzykiwania zależności.

Identity jest włączona przez wywołanie metody UseAuthentication. UseAuthenticationDodaje oprogramowanie pośredniczące uwierzytelniania do potoku żądania.

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

Powyższy kod konfiguruje Identity z domyślnymi wartościami opcji. Usługi są udostępniane aplikacji za pośrednictwem wstrzykiwania zależności.

Identity jest włączona przez wywołanie metody UseAuthentication. UseAuthenticationDodaje oprogramowanie pośredniczące uwierzytelniania do potoku żądania.

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

Aplikacja wygenerowana przez szablon nie używa autoryzacji. app.UseAuthorization element jest uwzględniony, aby upewnić się, że jest dodawany w odpowiedniej kolejności, jeśli aplikacja doda autoryzację. UseRouting, , UseAuthenticationUseAuthorizationi UseEndpoints musi być wywoływana w kolejności pokazanej w poprzednim kodzie.

Aby uzyskać więcej informacji na temat IdentityOptions i Startup, zobacz IdentityOptions i Application Startup (Uruchamianie aplikacji).

Rejestrowanie szkieletu, logowanie, rejestrowanie i rejestrowanieKonfirmacja

RegisterDodaj pliki , Login, LogOuti RegisterConfirmation . Postępuj zgodnie z tożsamością szkieletu w Razor projekcie z instrukcjami autoryzacji , aby wygenerować kod pokazany w tej sekcji.

Sprawdzanie rejestru

Gdy użytkownik kliknie przycisk Zarejestruj na Register stronie, RegisterModel.OnPostAsync zostanie wywołana akcja. Użytkownik jest tworzony przez CreateAsync(TUser) użytkownika w _userManager obiekcie :

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

Wyłącz domyślną weryfikację konta

W przypadku szablonów domyślnych użytkownik jest przekierowywany do Account.RegisterConfirmation lokalizacji, w której może wybrać link, aby potwierdzić konto. Wartość domyślna Account.RegisterConfirmation jest używana tylko do testowania, automatyczna weryfikacja konta powinna być wyłączona w aplikacji produkcyjnej.

Aby wymagać potwierdzonego konta i zapobiec natychmiastowemu zalogowaniu podczas rejestracji, ustaw wartość w pliku DisplayConfirmAccountLink = false/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();
    }
}

Logowanie się

Formularz logowania jest wyświetlany, gdy:

  • Wybrano link Zaloguj .
  • Użytkownik próbuje uzyskać dostęp do strony z ograniczeniami, do której nie ma uprawnień dostępu lub gdy nie został uwierzytelniony przez system.

Po przesłaniu formularza na stronie Logowania akcja jest wywoływana OnPostAsync . PasswordSignInAsync element jest wywoływany _signInManager na obiekcie .

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

Aby uzyskać informacje na temat podejmowania decyzji dotyczących autoryzacji, zobacz Wprowadzenie do autoryzacji w programie ASP.NET Core.

Wyloguj się

Link WylogujLogoutModel.OnPost wywołuje akcję.

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

W poprzednim kodzie kod return RedirectToPage(); musi być przekierowaniem, aby przeglądarka wykonała nowe żądanie, a tożsamość użytkownika zostanie zaktualizowana.

SignOutAsync czyści oświadczenia użytkownika przechowywane w obiekcie cookie.

Wpis jest określony w pliku 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

Domyślne szablony projektów internetowych umożliwiają anonimowy dostęp do stron domowych. Aby przetestować Identitypolecenie , dodaj polecenie [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()
        {
        }
    }
}

Jeśli się zalogujesz, wyloguj się. Uruchom aplikację i wybierz Privacy link. Nastąpi przekierowanie do strony logowania.

Poznaj Identity

Aby zapoznać się Identity bardziej szczegółowo:

Identity Składniki

IdentityWszystkie pakiety NuGet zależne są zawarte w strukturze udostępnionej ASP.NET Core.

Podstawowym pakietem programu Identity jest Microsoft.AspNetCore.Identity. Ten pakiet zawiera podstawowy zestaw interfejsów dla ASP.NET Core Identityi jest uwzględniony przez Microsoft.AspNetCore.Identity.EntityFrameworkCoreprogram .

Migrowanie do platformy ASP.NET Core Identity

Aby uzyskać więcej informacji i wskazówek dotyczących migrowania istniejącego Identity magazynu, zobacz Migrowanie uwierzytelniania i Identity.

Ustawianie siły hasła

Zobacz Konfiguracja przykładu, który określa minimalne wymagania dotyczące hasła.

Zapobieganie publikowaniu zasobów statycznych Identity

Aby zapobiec publikowaniu statycznych Identity zasobów (arkuszy stylów i plików JavaScript dla Identity interfejsu użytkownika) w katalogu głównym sieci Web, dodaj następującą ResolveStaticWebAssetsInputsDependsOn właściwość i RemoveIdentityAssets element docelowy do pliku projektu aplikacji:

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

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

Następne kroki