Введение в Identity на ASP.NET Core
Автор: Рик Андерсон (Rick Anderson)
ASP.NET Core Identity:
- API, поддерживающий функциональность входа в пользовательский интерфейс.
- Управляет пользователями, паролями, данными профиля, ролями, утверждениями, маркерами, подтверждением электронной почты и т. д.
Пользователи могут создать учетную запись с данными логина, хранящимися в Identity, или использовать внешнего провайдера логина. Поддерживаемые внешние поставщики входа включают Facebook, Google, Учетную запись Майкрософт и Twitter.
Дополнительные сведения о том, как глобально требовать проверку подлинности всех пользователей, см. в разделе Требовать проверку подлинности пользователей.
Исходный Identity код доступен на сайте GitHub. Identity Шаблон и просмотр созданных файлов для просмотра взаимодействия с Identityшаблоном.
Identity обычно настраивается с помощью базы данных SQL Server для хранения имен пользователей, паролей и данных профиля. Кроме того, можно использовать другое постоянное хранилище, например хранилище таблиц Azure.
В этом разделе вы узнаете, как с помощью Identity зарегистрировать пользователя, войти в систему и выйти из неё. Примечание: шаблоны обрабатывают имя пользователя и электронную почту как одно и то же. Дополнительные инструкции по созданию приложений, которые используются Identity, см. в разделе "Дальнейшие действия".
ASP.NET Core Identity не связан с платформой идентификации Майкрософт. Платформа идентификации Майкрософт
- Эволюция платформы разработчиков Azure Active Directory (Azure AD).
- Альтернативное решение для идентификации и авторизации в приложениях ASP.NET Core.
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-API и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity Сервер
Duende Identity Server — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende Identity Server включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Внимание
Компания Duende Software может потребовать лицензионный сбор за использование Duende Identity Server в производственной среде. Дополнительные сведения см. в статье Миграция с ASP.NET Core 5.0 на 6.0.
Дополнительные сведения см. в документации по Duende Identity Server (на веб-сайте ПО Duende).
Просмотр или скачивание примера кода (как скачать).
Создание веб-приложения с проверкой подлинности
Создайте проект веб-приложения ASP.NET Core с отдельными учетными записями пользователей.
- Выберите шаблон Веб-приложение ASP.NET Core. Назовите проект WebApp1 таким же пространством имен, как у загруженного проекта. Щелкните OK.
- В поле входных данных Тип проверки подлинности выберите Отдельные учетные записи пользователей.
Созданный проект предоставляет ASP.NET Core Identity как библиотеку Razor классов. Библиотека классов IdentityRazor предоставляет точки доступа в области Identity
. Например:
- /Identity/Аккаунт/Вход
- /Identity/Account/Logout
- /Identity/Аккаунт/Управление
Применение миграции
Примените миграции для инициализации базы данных.
Выполните следующую команду в консоли диспетчер пакетов (PMC):
Update-Database
Проверка регистрации и входа
Запустите приложение и зарегистрируйте пользователя. В зависимости от размера экрана может потребоваться выбрать кнопку переключателя навигации, чтобы просмотреть ссылки "Регистрация и вход ".
Identity Просмотр базы данных
- В меню "Вид" выберите SQL Server обозреватель объектов (SSOX).
- Перейдите к (localdb)MSSQLLocalDB(SQL Server 13). Щелкните правой кнопкой мыши на dbo.AspNetUsers>Просмотр данных:
Настройка Identity служб
Службы добавляются в Program.cs
. Типичным шаблоном является вызов методов в следующем порядке:
Add{Service}
builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
options.User.RequireUniqueEmail = false;
});
builder.Services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
options.LoginPath = "/Identity/Account/Login";
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.SlidingExpiration = true;
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Предыдущий код настраивает Identity с параметрами по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication.
UseAuthentication
добавляет ПО промежуточного слоя проверки подлинности в конвейер запросов.
Созданное шаблоном приложение не использует авторизацию.
app.UseAuthorization
включается, чтобы убедиться, что он добавлен в правильном порядке, если приложение добавит авторизацию.
UseRouting
, UseAuthentication
и UseAuthorization
должен вызываться в порядке, приведенном в приведенном выше коде.
Для получения дополнительной информации о IdentityOptions
см. IdentityOptions и Запуск приложения.
Шаблон Register, Login, LogOut и RegisterConfirmation
Добавьте файлы Register
, Login
, LogOut
и RegisterConfirmation
. Следуйте идентификатору шаблона в проекте Razor с инструкциями по авторизации, чтобы сгенерировать код, показанный в этом разделе.
Проверка регистра
Когда пользователь нажимает кнопку "Зарегистрировать" на Register
странице, вызывается RegisterModel.OnPostAsync
действие. Пользователь создается пользователем CreateAsync(TUser) на объекте _userManager
.
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();
}
Отключение проверки учетной записи по умолчанию
При использовании шаблонов по умолчанию пользователь перенаправляется на Account.RegisterConfirmation
место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation
используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.
Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте 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();
}
}
Вход в систему
Форма входа отображается в следующих случаях:
- Выбрана ссылка на вход .
- Пользователь пытается получить доступ к ограниченной странице, к ней не разрешен доступ или когда он не прошел проверку подлинности в системе.
При отправке формы на странице входа вызывается действие OnPostAsync
.
PasswordSignInAsync
вызывается для _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();
}
Сведения о том, как принимать решения об авторизации, см. в разделе "Введение в авторизацию" в ASP.NET Core.
Выйти из системы
Ссылка выхода из системы вызывает 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();
}
}
}
}
В приведенном выше коде код return RedirectToPage();
должен переадресовываться, чтобы браузер выполнял новый запрос и идентификатор пользователя обновился.
SignOutAsync очищает утверждения пользователя, хранящиеся в объекте cookie.
Запись указана в 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>
Тест Identity
Шаблоны веб-проектов по умолчанию разрешают анонимный доступ к домашним страницам. Чтобы проверить Identity, добавьте [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()
{
}
}
}
Если вы вошли, выйдите. Запустите приложение и выберите ссылку Privacy. Вы перейдете на страницу входа.
Исследовать Identity
Чтобы подробнее изучить Identity:
- Полное создание пользовательского интерфейса для удостоверения личности
- Изучите исходный код каждой страницы и пошагово пройдите через отладчик.
Identity Компоненты
Все пакеты NuGet, зависящие от Identity, включены в общий фреймворк ASP.NET Core.
Основной пакет для Identity — это Microsoft.AspNetCore.Identity. Этот пакет содержит основной набор интерфейсов для ASP.NET Core Identity, и включён в Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Миграция на ASP.NET Core Identity
Дополнительные сведения и рекомендации по переносу существующего Identity хранилища см. в разделе Миграция проверки подлинности и Identity.
Настройка надежности пароля
Смотрите Конфигурация для примера, который задает минимальные требования к паролям.
AddDefaultIdentity и AddIdentity
AddDefaultIdentity появилась в ASP.NET Core 2.1. Вызов AddDefaultIdentity
аналогичен вызову следующего:
Подробнее см. в источнике AddDefaultIdentity.
Предотвращение публикации статических Identity ресурсов
Чтобы предотвратить публикацию статических Identity ресурсов (таблиц стилей и файлов JavaScript для Identity пользовательского интерфейса) в корневой веб-сайт, добавьте следующее ResolveStaticWebAssetsInputsDependsOn
свойство и RemoveIdentityAssets
целевой объект в файл проекта приложения:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Следующие шаги
- См. этот выпуск GitHub для получения информации о настройке Identity с помощью SQLite.
- Настройка Identity
- Создание приложения ASP.NET Core с защитой данных пользователя с помощью авторизации
- Добавление, скачивание и удаление пользовательских данных Identity в проект ASP.NET Core
- Включение создания QR-кодов для приложений проверки подлинности TOTP в ASP.NET Core
- Перенос проверки подлинности и Identity на ASP.NET Core
- Подтверждение учетной записи и восстановление пароля в ASP.NET Core
- Двухфакторная проверка подлинности с помощью SMS в ASP.NET Core
- Разместить ASP.NET Core в веб-ферме
Автор: Рик Андерсон (Rick Anderson)
ASP.NET Core Identity:
- API, поддерживающий функциональность входа в пользовательский интерфейс.
- Управляет пользователями, паролями, данными профиля, ролями, утверждениями, маркерами, подтверждением электронной почты и т. д.
Пользователи могут создать учетную запись с данными для входа, которые сохраняются в Identity, или использовать внешний провайдер аутентификации. Поддерживаемые внешние поставщики входа включают Facebook, Google, Учетную запись Майкрософт и Twitter.
Дополнительные сведения о том, как глобально требовать проверку подлинности всех пользователей, см. в разделе Требовать проверку подлинности пользователей.
Исходный Identity код доступен на сайте GitHub. Identity Шаблон и просмотр созданных файлов для просмотра взаимодействия с Identityшаблоном.
Identity обычно настраивается с помощью базы данных SQL Server для хранения имен пользователей, паролей и данных профиля. Кроме того, можно использовать другое постоянное хранилище, например хранилище таблиц Azure.
В этой теме вы узнаете, как использовать Identity для регистрации пользователя, входа и выхода из его учетной записи. Примечание: Шаблоны обрабатывают имя пользователя и электронную почту как одно и то же. Дополнительные инструкции по созданию приложений, которые используются Identity, см. в разделе "Дальнейшие действия".
платформа удостоверений Майкрософт:
- Эволюция платформы разработчиков Azure Active Directory (Azure AD).
- Альтернативное решение для идентификации и авторизации в приложениях ASP.NET Core.
- Не связан с ASP.NET Core Identity.
ASP.NET Core Identity позволяет использовать функцию входа в пользовательском интерфейсе для веб-приложений ASP.NET Core. Чтобы защитить веб-интерфейсы программирования приложений (API) и одностраничные приложения, используйте один из следующих способов:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende IdentityServer. Duende IdentityServer — это сторонний продукт.
Duende IdentityServer — это платформа OpenID Connect и OAuth 2.0 для ASP.NET Core. Duende IdentityServer включает следующие функции безопасности:
- Проверка подлинности как услуга (AaaS)
- Единый вход и выход (SSO) для нескольких типов приложений
- Контроль доступа для API
- Шлюз федерации
Дополнительные сведения см. в разделе "Обзор Duende IdentityServer".
Дополнительные сведения о других поставщиках проверки подлинности см. в разделе "Параметры проверки подлинности Community OSS" для ASP.NET Core
Просмотр или скачивание примера кода (как скачать).
Создание веб-приложения с проверкой подлинности
Создайте проект веб-приложения ASP.NET Core с отдельными учетными записями пользователей.
- Выберите Файл > Создать > Проект.
- Выберите Веб-приложение ASP.NET Core. Назовите проект WebApp1, чтобы он совпадал с пространством имен загружаемого проекта. Щелкните OK.
- Выберите веб-приложение ASP.NET Core, а затем нажмите кнопку "Изменить проверку подлинности".
- Выберите отдельные учетные записи пользователей и нажмите кнопку "ОК".
Созданный проект предоставляет библиотеку классов ASP.NET Core IdentityRazor. Библиотека IdentityRazor классов предоставляет конечные точки с областью Identity
. Например:
- /Identity/Аккаунт/Войти
- /Identity/Account/Logout
- /Identity/Аккаунт/Управление
Применение миграции
Примените миграции для инициализации базы данных.
Выполните следующую команду в консоли диспетчер пакетов (PMC):
PM> Update-Database
Проверка регистрации и входа
Запустите приложение и зарегистрируйте пользователя. В зависимости от размера экрана может потребоваться выбрать кнопку переключателя навигации, чтобы просмотреть ссылки "Регистрация и вход ".
Identity Просмотр базы данных
- В меню "Вид" выберите SQL Server обозреватель объектов (SSOX).
- Перейдите к (localdb)MSSQLLocalDB(SQL Server 13). Щелкните правой кнопкой мыши dbo.AspNetUsers>Просмотр данных:
Настройка Identity служб
Службы добавляются в ConfigureServices
. По стандартному шаблону сначала вызываются все методы Add{Service}
, а затем все методы services.Configure{Service}
.
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;
});
}
Предыдущий выделенный код настраивает Identity со значениями параметров по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication.
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;
});
}
Предыдущий код настраивает Identity с параметрами по умолчанию. Службы становятся доступными для приложения с помощью внедрения зависимостей.
Identity включен путем вызова UseAuthentication.
UseAuthentication
добавляет в конвейер запросов промежуточное программное обеспечение проверки подлинности.
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();
});
}
Созданное шаблоном приложение не использует авторизацию.
app.UseAuthorization
включается, чтобы убедиться, что он добавлен в правильном порядке, если приложение добавит авторизацию.
UseRouting
, UseAuthentication
, UseAuthorization
и UseEndpoints
должен вызываться в порядке, приведенном в предыдущем коде.
Дополнительные сведения о IdentityOptions
и Startup
см. в разделе IdentityOptions и Запуск приложения.
Шаблон регистрации, входа в систему, выхода из системы и подтверждения регистрации
Добавьте файлы Register
, Login
, LogOut
и RegisterConfirmation
. Следуйте идентификатору шаблона в проекте Razor с инструкциями по авторизации, чтобы сгенерировать код, показанный в этом разделе.
Проверка регистра
Когда пользователь нажимает кнопку "Зарегистрировать" на странице Register
, вызывается действие RegisterModel.OnPostAsync
. Пользователь создается CreateAsync(TUser) в объекте _userManager
:
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();
}
Отключение проверки учетной записи по умолчанию
При использовании шаблонов по умолчанию пользователь перенаправляется на Account.RegisterConfirmation
место, где можно выбрать ссылку, чтобы подтвердить учетную запись. Значение по умолчанию Account.RegisterConfirmation
используется только для тестирования, автоматическая проверка учетной записи должна быть отключена в рабочем приложении.
Чтобы требовать подтвержденную учетную запись и предотвратить немедленный вход при регистрации, задайте 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();
}
}
Вход в систему
Форма входа отображается в следующих случаях:
- Выбрана ссылка на вход .
- Пользователь пытается получить доступ к ограниченной странице, к ней не разрешен доступ или когда он не прошел проверку подлинности в системе.
При отправке формы на странице входа вызывается действие OnPostAsync
.
PasswordSignInAsync
вызывается для _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();
}
Сведения о том, как принимать решения об авторизации, см. в разделе "Введение в авторизацию" в ASP.NET Core.
Выйти из системы
Ссылка Выйти вызывает 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();
}
}
}
}
В приведенном выше коде код return RedirectToPage();
должен переадресовываться, чтобы браузер выполнял новый запрос и идентификатор пользователя обновился.
SignOutAsync очищает утверждения пользователя, хранящиеся в объекте cookie.
Запись указана в 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>
Тест Identity
Шаблоны веб-проектов по умолчанию разрешают анонимный доступ к домашним страницам. Чтобы проверить Identity, добавьте [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()
{
}
}
}
Если вы вошли в систему, выйдите из учетной записи. Запустите приложение и выберите ссылку Privacy. Вы перейдете на страницу входа.
Исследовать Identity
Чтобы изучить Identity более подробно:
- Полное создание пользовательского интерфейса для удостоверения личности
- Изучите источник каждой страницы и выполните шаг через отладчик.
Identity Компоненты
Все пакеты NuGet, зависящие от Identity, включены в общий фреймворк ASP.NET Core.
Основной пакет для Identity — это Microsoft.AspNetCore.Identity. Этот пакет содержит основной набор интерфейсов для ASP.NET Core Identity, и пакет включен в состав Microsoft.AspNetCore.Identity.EntityFrameworkCore
.
Миграция на ASP.NET Core Identity
Для получения более подробной информации и рекомендаций по переносу существующего Identity хранилища смотрите раздел «Миграция проверки подлинности и Identity».
Настройка надежности пароля
См. Конфигурацию для примера, который задает минимальные требования к паролю.
Запрет на публикацию статических Identity ресурсов
Чтобы предотвратить публикацию статических Identity ресурсов (таблиц стилей и файлов JavaScript для Identity пользовательского интерфейса) в корневой веб-сайт, добавьте следующее ResolveStaticWebAssetsInputsDependsOn
свойство и RemoveIdentityAssets
целевой объект в файл проекта приложения:
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>
<Target Name="RemoveIdentityAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
</ItemGroup>
</Target>
Следующие шаги
- исходный код ASP.NET Core Identity
- Источник AddDefaultIdentity
- Посмотрите этот запрос на GitHub для получения информации о настройке Identity с помощью SQLite.
- Настройка Identity
- Создание приложения ASP.NET Core с защитой данных пользователя с помощью авторизации
- Добавление, скачивание и удаление пользовательских данных Identity в проект ASP.NET Core
- Включение создания QR-кодов для приложений проверки подлинности TOTP в ASP.NET Core
- Миграция аутентификации на ASP.NET CoreIdentity
- Подтверждение учетной записи и восстановление пароля в ASP.NET Core
- Двухфакторная проверка подлинности с помощью SMS в ASP.NET Core
- Разместите ASP.NET Core на веб-ферме
ASP.NET Core