Compartir vía


Introducción a Identity en ASP.NET Core

ASP.NET CoreIdentity:

  • Es una API que admite la funcionalidad de inicio de sesión de la interfaz de usuario (UI).
  • Administra usuarios, contraseñas, datos de perfil, roles, notificaciones, tokens, confirmación por correo electrónico, etc.

Los usuarios pueden crear una cuenta con la información de inicio de sesión almacenada en Identity o pueden usar un proveedor de inicio de sesión externo. Los proveedores de inicios de sesión externos admitidos incluyen Facebook, Google, Cuenta microsoft y Twitter.

Para obtener información sobre cómo requerir globalmente que todos los usuarios se autentiquen, consulte Requerir usuarios autenticados.

El Identity código fuente está disponible en GitHub. Andamio Identity y ver los archivos generados para revisar la interacción de la plantilla con Identity.

Identity suele configurarse usando una base de datos de SQL Server para almacenar nombres de usuario, contraseñas y datos de perfil. Como alternativa, se puede usar otro almacén persistente, por ejemplo, Azure Table Storage.

En este tema, obtendrás información sobre cómo usar Identity para registrar un usuario e iniciar o cerrar su sesión. Nota: las plantillas tratan el nombre de usuario y el correo electrónico como los mismos para los usuarios. Para obtener instrucciones más detalladas sobre cómo crear aplicaciones que usan Identity, consulte Pasos siguientes.

Para obtener más información sobre Identity en aplicaciones Blazor, consulte Autenticación y autorización de ASP.NET CoreBlazor y los artículos que le siguen en la documentación de Blazor.

ASP.NET Core Identity no está relacionado con la plataforma de identidad de Microsoft . La plataforma de identidad de Microsoft es:

  • Una evolución de la plataforma para desarrolladores de Azure Active Directory (Azure AD).
  • Una solución de identidad alternativa para la autenticación y autorización en aplicaciones ASP.NET Core.

ASP.NET Core Identity agrega la funcionalidad de inicio de sesión de la interfaz de usuario (IU) a las aplicaciones web de ASP.NET Core. Para proteger las API web y las SPA, usa una de las siguientes opciones:

Duende Identity Server es un marco de OpenID Connect y OAuth 2.0 para ASP.NET Core. Duende Identity Server permite las siguientes características de seguridad:

  • Autenticación como servicio (AaaS)
  • Inicio de sesión único (SSO) mediante varios tipos de aplicaciones
  • Control de acceso para API
  • Puerta de enlace de federación

Importante

Duende Software puede requerir que pague una tarifa de licencia para el uso de producción de Duende Identity Server. Para obtener más información, consulte Migración de ASP.NET Core en .NET 5 a .NET 6.

Para obtener más información, consulte la documentación de Duende Identity Server (sitio web de Duende Software).

Vea o descargue el código de ejemplo (cómo descargar).

Creación de una Blazor Web App con autenticación

Cree un proyecto de ASP.NET Core Blazor Web App con cuentas individuales.

Nota:

Para obtener una experiencia de Razor Pages, vea la sección Crear una aplicación Razor Pages con autenticación.

Para obtener una experiencia de MVC, consulte la sección Creación de una aplicación MVC con autenticación .

  • Seleccione la Blazor Web App plantilla. Seleccione Siguiente.
  • Realice las siguientes selecciones:
    • Tipo de autenticación: Cuentas individuales
    • Modo de representación interactiva: Servidor
    • Ubicación de interactividad: Global
  • Selecciona Crear.

El proyecto generado incluye IdentityRazor componentes. Los componentes se encuentran en la Components/Account carpeta . Por ejemplo:

  • /Components/Account/Pages/Register
  • /Components/Account/Pages/Login
  • /Components/Account/Pages/Manage/ChangePassword

IdentityRazor Los componentes se describen individualmente en la documentación de casos de uso específicos y están sujetos a cambios en cada versión. Al generar un Blazor Web App con cuentas individuales, IdentityRazor los componentes se incluyen en el proyecto generado. Los IdentityRazor componentes también se pueden inspeccionar en la Blazor plantilla de proyecto en el origen de referencia de ASP.NET Core (dotnet/aspnetcorerepositorio de GitHub).

Nota:

Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta para una versión específica, use la lista desplegable Cambiar ramas o etiquetas . Para obtener más información, vea Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Para obtener más información, consulte autenticación y autorización en ASP.NET CoreBlazor y los artículos que le siguen en la documentación Blazor. La mayoría de los artículos del área Seguridad y Identity del conjunto de documentación principal de ASP.NET Core se aplican a Blazor las aplicaciones. Sin embargo, el Blazor conjunto de documentación contiene artículos e instrucciones que reemplazan o agregan información. Se recomienda estudiar primero el conjunto de documentación general de ASP.NET Core, seguido de acceder a los artículos en la documentación de Blazorseguridad y Identity.

Crea una Razor aplicación Pages con autenticación

Cree un proyecto de aplicación web principal (Razor Páginas) de ASP.NET con cuentas individuales.

  • Seleccione la plantilla ASP.NET Core Web App (Razor Pages). Seleccione Siguiente.
  • En Tipo de autenticación, seleccione Cuentas individuales.
  • Selecciona Crear.

El proyecto generado proporciona ASP.NET Core Identity como bibliotecaRazor de clases (RCL). La biblioteca de clases IdentityRazor expone puntos de conexión con el área Identity. Por ejemplo:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Las páginas se describen individualmente en la documentación de casos de uso específicos y están sujetas a cambios en cada versión. Para ver todas las páginas de la RCL, consulte el origen de referencia de ASP.NET Core (dotnet/aspnetcorerepositorio de GitHub, Identity/UI/src/Areas/Identity/Pages carpeta). Puede estructurar páginas individuales o todas las páginas dentro de la aplicación. Para obtener más información, consulta Scaffolding Identity en proyectos de ASP.NET Core.

Creación de una aplicación MVC con autenticación

Cree un proyecto de MVC de ASP.NET Core con cuentas individuales.

  • Seleccione la plantilla ASP.NET Core Web App (Model-View-Controller). Seleccione Siguiente.
  • En Tipo de autenticación, seleccione Cuentas individuales.
  • Selecciona Crear.

El proyecto generado proporciona ASP.NET Core Identity como bibliotecaRazor de clases (RCL). La biblioteca de clases IdentityRazor se basa en Razor Pages y expone puntos de conexión con el área Identity. Por ejemplo:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Las páginas se describen individualmente en la documentación de casos de uso específicos y están sujetas a cambios en cada versión. Para ver todas las páginas de la RCL, consulte el origen de referencia de ASP.NET Core (dotnet/aspnetcorerepositorio de GitHub, Identity/UI/src/Areas/Identity/Pages carpeta). Puede aplicar scaffolding a páginas individuales o todas las páginas de la aplicación. Para obtener más información, consulta Scaffolding Identity en proyectos de ASP.NET Core.

Aplicación de migraciones

Aplica las migraciones para inicializar la base de datos.

Ejecuta el siguiente comando en la consola del administrador de paquetes (PMC):

Update-Database

Prueba del registro e inicio de sesión

Ejecuta la aplicación y registra un usuario. Según el tamaño de la pantalla, es posible que tenga que seleccionar el botón de alternancia de navegación para ver los vínculos Registrar e Iniciar sesión .

Ver la base de datos Identity

  • En el menú Ver , seleccione Explorador de objetos de SQL Server (SSOX).
  • Vaya a (localdb)MSSQLLocalDB(SQL Server 13). Haga clic con el botón derecho en dbo.AspNetUsers>Ver datos:

Menú contextual de la tabla AspNetUsers en el Explorador de objetos de SQL Server

Configuración de servicios de Identity

Los servicios se agregan en Program.cs. El patrón típico es llamar a métodos en el orden siguiente:

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

El código anterior configura Identity con los valores predeterminados de las opciones. Los servicios están disponibles para la aplicación a través de la inserción de dependencias.

Identity se habilita llamando a UseAuthentication. UseAuthentication agrega middleware de autenticación a la canalización de solicitudes.

La aplicación generada por plantillas no usa la autorización. app.UseAuthorization se incluye para asegurar que se agrega en el orden correcto en caso de que la aplicación agregue la autorización. Se debe llamar a UseRouting, UseAuthentication y UseAuthorization en el orden mostrado en el código anterior.

Para obtener más información sobre IdentityOptions, vea IdentityOptions y Inicio de la aplicación.

Scaffold Register, Login, LogOut y RegisterConfirmation

Agrega los archivos Register, Login, LogOut y RegisterConfirmation. Siga las instrucciones de Scaffold identity en un proyecto Razor con autorización para generar el código que se muestra en esta sección.

Examen del registro

Cuando un usuario hace clic en el botón Registrar de la Register página, se invoca la RegisterModel.OnPostAsync acción. El usuario es creado por CreateAsync(TUser) en el objeto _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();
}

Deshabilitar la verificación de la cuenta predeterminada

Con las plantillas predeterminadas, se redirige al usuario al Account.RegisterConfirmation donde puede seleccionar un vínculo para que se confirme la cuenta. El valor predeterminado Account.RegisterConfirmationsolo se usa para las pruebas, la comprobación automática de la cuenta debe deshabilitarse en una aplicación de producción.

Para requerir una cuenta confirmada e impedir el inicio de sesión inmediato en el registro, establezca DisplayConfirmAccountLink = false en /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();
    }
}

Iniciar sesión

El formulario de inicio de sesión aparece cuando:

  • El vínculo Iniciar sesión está seleccionado.
  • Un usuario intenta acceder a una página restringida a la que no está autorizado para acceder o cuando el sistema no lo ha autenticado.

Cuando se envía el formulario en la página Inicio de sesión, se llama a la acción OnPostAsync. Se llama a PasswordSignInAsync en el objeto _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();
}

Para obtener información sobre cómo tomar decisiones de autorización, consulte Introducción a la autorización en ASP.NET Core.

Cerrar sesión

El vínculo Cerrar sesión invoca la LogoutModel.OnPost acción.

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

En el código anterior, el código return RedirectToPage(); debe ser una redirección para que el explorador realice una nueva solicitud y la identidad del usuario se actualice.

SignOutAsync borra las notificaciones del usuario almacenadas en cookie.

La publicación se especifica en 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>

Probar Identity

Las plantillas de proyecto web predeterminadas permiten el acceso anónimo a las páginas principales. Para probar Identity, agregue [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()
        {
        }
    }
}

Si ha iniciado sesión, cierre la sesión. Ejecute la aplicación y seleccione el vínculo Privacy. Se le redirige a la página de inicio de sesión.

Explorar Identity

Para explorar Identity con más detalle:

Identity Componentes

Todos los Identitypaquetes NuGet dependientes se incluyen en el marco compartido de ASP.NET Core.

El paquete principal de Identity es Microsoft.AspNetCore.Identity. Este paquete contiene el conjunto básico de interfaces para ASP.NET Core Identity, y está incluido por Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migración a ASP.NET Core Identity

Para obtener más información e instrucciones sobre cómo migrar el almacén existente Identity , consulte Migración de la autenticación y Identity.

Establecimiento de la seguridad de la contraseña

Consulte Configuración para obtener un ejemplo que establezca los requisitos mínimos de contraseña.

AddDefaultIdentity y AddIdentity

AddDefaultIdentity se introdujo en ASP.NET Core 2.1. Llamar a AddDefaultIdentity es similar a llamar a lo siguiente:

Consulte AddDefaultIdentity source para obtener más información.

Impedir la publicación de recursos estáticos Identity

Para evitar la publicación de recursos estáticos Identity (hojas de estilos y archivos de JavaScript para la interfaz de usuario de Identity) en la raíz web, agregue la siguiente propiedad ResolveStaticWebAssetsInputsDependsOn y el destino RemoveIdentityAssets al archivo de proyecto de la aplicación:

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

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

Pasos siguientes

Por Rick Anderson

ASP.NET CoreIdentity:

  • Es una API que admite la funcionalidad de inicio de sesión de la interfaz de usuario (UI).
  • Administra usuarios, contraseñas, datos de perfil, roles, notificaciones, tokens, confirmación por correo electrónico, etc.

Los usuarios pueden crear una cuenta con la información de inicio de sesión almacenada en Identity o pueden usar un proveedor de inicio de sesión externo. Los proveedores de inicios de sesión externos admitidos incluyen Facebook, Google, Cuenta microsoft y Twitter.

Para obtener información sobre cómo requerir globalmente que todos los usuarios se autentiquen, consulte Requerir usuarios autenticados.

El Identity código fuente está disponible en GitHub. Andamio Identity y ver los archivos generados para revisar la interacción de la plantilla con Identity.

Identity suele configurarse usando una base de datos de SQL Server para almacenar nombres de usuario, contraseñas y datos de perfil. Como alternativa, se puede usar otro almacén persistente, por ejemplo, Azure Table Storage.

En este tema, obtendrás información sobre cómo usar Identity para registrar un usuario e iniciar o cerrar su sesión. Nota: las plantillas tratan el nombre de usuario y el correo electrónico como los mismos para los usuarios. Para obtener instrucciones más detalladas sobre cómo crear aplicaciones que usan Identity, consulte Pasos siguientes.

ASP.NET Core Identity no está relacionado con la plataforma de identidad de Microsoft . La plataforma de identidad de Microsoft es:

  • Una evolución de la plataforma para desarrolladores de Azure Active Directory (Azure AD).
  • Una solución de identidad alternativa para la autenticación y autorización en aplicaciones ASP.NET Core.

ASP.NET Core Identity agrega la funcionalidad de inicio de sesión de la interfaz de usuario (IU) a las aplicaciones web de ASP.NET Core. Para proteger las API web y las SPA, usa una de las siguientes opciones:

Duende Identity Server es un marco de OpenID Connect y OAuth 2.0 para ASP.NET Core. Duende Identity Server permite las siguientes características de seguridad:

  • Autenticación como servicio (AaaS)
  • Inicio de sesión único (SSO) mediante varios tipos de aplicaciones
  • Control de acceso para API
  • Puerta de enlace de federación

Importante

Duende Software puede requerir que pague una tarifa de licencia para el uso de producción de Duende Identity Server. Para obtener más información, consulte Migración de ASP.NET Core en .NET 5 a .NET 6.

Para obtener más información, consulte la documentación de Duende Identity Server (sitio web de Duende Software).

Vea o descargue el código de ejemplo (cómo descargar).

Creación de una aplicación web con autenticación

Crea un proyecto de aplicación web de ASP.NET Core con cuentas de usuario individuales.

  • Seleccione la plantilla ASP.NET Core Web App . Asigne al proyecto el nombre WebApp1 para que tenga el mismo espacio de nombres que la descarga del proyecto. Haga clic en Aceptar.
  • En la entrada Tipo de autenticación , seleccione Cuentas de usuario individuales.

El proyecto generado proporciona ASP.NET Core Identity como bibliotecaRazor de clases. La biblioteca de clases IdentityRazor expone puntos de conexión con el área Identity. Por ejemplo:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Cuenta/Administrar

Aplicación de migraciones

Aplica las migraciones para inicializar la base de datos.

Ejecuta el siguiente comando en la consola del administrador de paquetes (PMC):

Update-Database

Prueba del registro e inicio de sesión

Ejecuta la aplicación y registra un usuario. Según el tamaño de la pantalla, es posible que tenga que seleccionar el botón de alternancia de navegación para ver los vínculos Registrar e Iniciar sesión .

Ver la base de datos Identity

  • En el menú Ver , seleccione Explorador de objetos de SQL Server (SSOX).
  • Vaya a (localdb)MSSQLLocalDB(SQL Server 13). Haga clic con el botón derecho en dbo.AspNetUsers>Ver datos:

Menú contextual de la tabla AspNetUsers en el Explorador de objetos de SQL Server

Configuración de servicios de Identity

Los servicios se agregan en Program.cs. El patrón típico es llamar a métodos en el orden siguiente:

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

El código anterior configura Identity con los valores predeterminados de las opciones. Los servicios están disponibles para la aplicación a través de la inserción de dependencias.

Identity se habilita llamando a UseAuthentication. UseAuthentication agrega middleware de autenticación a la canalización de solicitudes.

La aplicación generada por plantillas no usa la autorización. app.UseAuthorization se incluye para asegurar que se agrega en el orden correcto en caso de que la aplicación agregue la autorización. Se debe llamar a UseRouting, UseAuthentication y UseAuthorization en el orden mostrado en el código anterior.

Para obtener más información sobre IdentityOptions, vea IdentityOptions y Inicio de la aplicación.

Scaffold Register, Login, LogOut y RegisterConfirmation

Agrega los archivos Register, Login, LogOut y RegisterConfirmation. Siga las instrucciones de Scaffold identity en un proyecto Razor con autorización para generar el código que se muestra en esta sección.

Examen del registro

Cuando un usuario hace clic en el botón Registrar de la Register página, se invoca la RegisterModel.OnPostAsync acción. El usuario es creado por CreateAsync(TUser) en el objeto _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();
}

Deshabilitar la verificación de la cuenta predeterminada

Con las plantillas predeterminadas, se redirige al usuario al Account.RegisterConfirmation donde puede seleccionar un vínculo para que se confirme la cuenta. El valor predeterminado Account.RegisterConfirmationsolo se usa para las pruebas, la comprobación automática de la cuenta debe deshabilitarse en una aplicación de producción.

Para requerir una cuenta confirmada e impedir el inicio de sesión inmediato en el registro, establezca DisplayConfirmAccountLink = false en /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();
    }
}

Iniciar sesión

El formulario de inicio de sesión aparece cuando:

  • El vínculo Iniciar sesión está seleccionado.
  • Un usuario intenta acceder a una página restringida a la que no está autorizado para acceder o cuando el sistema no lo ha autenticado.

Cuando se envía el formulario en la página Inicio de sesión, se llama a la acción OnPostAsync. Se llama a PasswordSignInAsync en el objeto _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();
}

Para obtener información sobre cómo tomar decisiones de autorización, consulte Introducción a la autorización en ASP.NET Core.

Cerrar sesión

El vínculo Cerrar sesión invoca la LogoutModel.OnPost acción.

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

En el código anterior, el código return RedirectToPage(); debe ser una redirección para que el explorador realice una nueva solicitud y la identidad del usuario se actualice.

SignOutAsync borra las notificaciones del usuario almacenadas en cookie.

La publicación se especifica en 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>

Probar Identity

Las plantillas de proyecto web predeterminadas permiten el acceso anónimo a las páginas principales. Para probar Identity, agregue [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()
        {
        }
    }
}

Si ha iniciado sesión, cierre la sesión. Ejecute la aplicación y seleccione el vínculo Privacy. Se le redirige a la página de inicio de sesión.

Explorar Identity

Para explorar Identity con más detalle:

Identity Componentes

Todos los Identitypaquetes NuGet dependientes se incluyen en el marco compartido de ASP.NET Core.

El paquete principal de Identity es Microsoft.AspNetCore.Identity. Este paquete contiene el conjunto básico de interfaces para ASP.NET Core Identity, y está incluido por Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migración a ASP.NET Core Identity

Para obtener más información e instrucciones sobre cómo migrar el almacén existente Identity , consulte Migración de la autenticación y Identity.

Establecimiento de la seguridad de la contraseña

Consulte Configuración para obtener un ejemplo que establezca los requisitos mínimos de contraseña.

AddDefaultIdentity y AddIdentity

AddDefaultIdentity se introdujo en ASP.NET Core 2.1. Llamar a AddDefaultIdentity es similar a llamar a lo siguiente:

Consulte AddDefaultIdentity source para obtener más información.

Impedir la publicación de recursos estáticos Identity

Para evitar la publicación de recursos estáticos Identity (hojas de estilos y archivos de JavaScript para la interfaz de usuario de Identity) en la raíz web, agregue la siguiente propiedad ResolveStaticWebAssetsInputsDependsOn y el destino RemoveIdentityAssets al archivo de proyecto de la aplicación:

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

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

Pasos siguientes

Por Rick Anderson

ASP.NET CoreIdentity:

  • Es una API que admite la funcionalidad de inicio de sesión de la interfaz de usuario (UI).
  • Administra usuarios, contraseñas, datos de perfil, roles, notificaciones, tokens, confirmación por correo electrónico, etc.

Los usuarios pueden crear una cuenta con la información de inicio de sesión almacenada en Identity o pueden usar un proveedor de inicio de sesión externo. Los proveedores de inicios de sesión externos admitidos incluyen Facebook, Google, Cuenta microsoft y Twitter.

Para obtener información sobre cómo requerir globalmente que todos los usuarios se autentiquen, consulte Requerir usuarios autenticados.

El Identity código fuente está disponible en GitHub. Andamio Identity y ver los archivos generados para revisar la interacción de la plantilla con Identity.

Identity suele configurarse usando una base de datos de SQL Server para almacenar nombres de usuario, contraseñas y datos de perfil. Como alternativa, se puede usar otro almacén persistente, por ejemplo, Azure Table Storage.

En este tema, obtendrás información sobre cómo usar Identity para registrar un usuario e iniciar o cerrar su sesión. Nota: las plantillas tratan el nombre de usuario y el correo electrónico como los mismos para los usuarios. Para obtener instrucciones más detalladas sobre cómo crear aplicaciones que usan Identity, consulte Pasos siguientes.

La plataforma de identidad de Microsoft es:

  • Una evolución de la plataforma para desarrolladores de Azure Active Directory (Azure AD).
  • Una solución de identidad alternativa para la autenticación y autorización en aplicaciones ASP.NET Core.
  • No relacionado con ASP.NET Core Identity.

ASP.NET Core Identity agrega la funcionalidad de inicio de sesión de la interfaz de usuario (IU) a las aplicaciones web de ASP.NET Core. Para proteger las API web y las SPA, usa una de las siguientes opciones:

Duende IdentityServer es un marco de OpenID Connect y OAuth 2.0 para ASP.NET Core. Duende IdentityServer habilita las siguientes características de seguridad:

  • Autenticación como servicio (AaaS)
  • Inicio de sesión único (SSO) mediante varios tipos de aplicaciones
  • Control de acceso para API
  • Puerta de enlace de federación

Para obtener más información, consulte Introducción a Duende IdentityServer.

Para obtener más información sobre otros proveedores de autenticación, consulte Opciones de autenticación del sistema operativo de la comunidad para ASP.NET Core.

Vea o descargue el código de ejemplo (cómo descargar).

Creación de una aplicación web con autenticación

Crea un proyecto de aplicación web de ASP.NET Core con cuentas de usuario individuales.

  • Seleccione Archivo>Nuevo>Proyecto.
  • Seleccione ASP.NET Aplicación web principal. Asigne al proyecto el nombre WebApp1 para que tenga el mismo espacio de nombres que la descarga del proyecto. Haga clic en Aceptar.
  • Seleccione un ASP.NET Aplicación web principal y, a continuación, seleccione Cambiar autenticación.
  • Seleccione Cuentas de usuario individuales y haga clic en Aceptar.

El proyecto generado proporciona ASP.NET Core Identity como bibliotecaRazor de clases. La biblioteca de clases IdentityRazor expone puntos de conexión con el área Identity. Por ejemplo:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Cuenta/Administrar

Aplicación de migraciones

Aplica las migraciones para inicializar la base de datos.

Ejecuta el siguiente comando en la consola del administrador de paquetes (PMC):

PM> Update-Database

Prueba del registro e inicio de sesión

Ejecuta la aplicación y registra un usuario. Según el tamaño de la pantalla, es posible que tenga que seleccionar el botón de alternancia de navegación para ver los vínculos Registrar e Iniciar sesión .

Ver la base de datos Identity

  • En el menú Ver , seleccione Explorador de objetos de SQL Server (SSOX).
  • Vaya a (localdb)MSSQLLocalDB(SQL Server 13). Haga clic con el botón derecho en dbo.AspNetUsers>Ver datos:

Menú contextual de la tabla AspNetUsers en el Explorador de objetos de SQL Server

Configuración de servicios de Identity

Los servicios se agregan en ConfigureServices. El patrón habitual consiste en llamar a todos los métodos Add{Service} y, luego, a todos los métodos 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;
    });
}

El código resaltado anterior configura Identity con los valores predeterminados de las opciones. Los servicios están disponibles para la aplicación a través de la inserción de dependencias.

Identity se habilita llamando a UseAuthentication. UseAuthentication agrega middleware de autenticación a la canalización de solicitudes.

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

El código anterior configura Identity con los valores predeterminados de las opciones. Los servicios están disponibles para la aplicación a través de la inserción de dependencias.

Identity se habilita llamando a UseAuthentication. UseAuthentication agrega middleware de autenticación a la canalización de solicitudes.

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

La aplicación generada por plantillas no usa la autorización. app.UseAuthorization se incluye para asegurar que se agrega en el orden correcto en caso de que la aplicación agregue la autorización. Se debe llamar a UseRouting, UseAuthentication, UseAuthorization y UseEndpoints en el orden mostrado en el código anterior.

Para obtener más información sobre IdentityOptions y Startup, vea IdentityOptions y Inicio de la aplicación.

Scaffold Register, Login, LogOut y RegisterConfirmation

Agrega los archivos Register, Login, LogOut y RegisterConfirmation. Siga las instrucciones de Scaffold identity en un proyecto Razor con autorización para generar el código que se muestra en esta sección.

Examen del registro

Cuando un usuario hace clic en el botón Registrar de la Register página, se invoca la RegisterModel.OnPostAsync acción. El usuario es creado por CreateAsync(TUser) en el objeto _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();
}

Deshabilitar la verificación de la cuenta predeterminada

Con las plantillas predeterminadas, se redirige al usuario al Account.RegisterConfirmation donde puede seleccionar un vínculo para que se confirme la cuenta. El valor predeterminado Account.RegisterConfirmationsolo se usa para las pruebas, la comprobación automática de la cuenta debe deshabilitarse en una aplicación de producción.

Para requerir una cuenta confirmada e impedir el inicio de sesión inmediato en el registro, establezca DisplayConfirmAccountLink = false en /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();
    }
}

Iniciar sesión

El formulario de inicio de sesión aparece cuando:

  • El vínculo Iniciar sesión está seleccionado.
  • Un usuario intenta acceder a una página restringida a la que no está autorizado para acceder o cuando el sistema no lo ha autenticado.

Cuando se envía el formulario en la página Inicio de sesión, se llama a la acción OnPostAsync. Se llama a PasswordSignInAsync en el objeto _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();
}

Para obtener información sobre cómo tomar decisiones de autorización, consulte Introducción a la autorización en ASP.NET Core.

Cerrar sesión

El vínculo Cerrar sesión invoca la LogoutModel.OnPost acción.

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

En el código anterior, el código return RedirectToPage(); debe ser una redirección para que el explorador realice una nueva solicitud y la identidad del usuario se actualice.

SignOutAsync borra las notificaciones del usuario almacenadas en cookie.

La publicación se especifica en 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>

Probar Identity

Las plantillas de proyecto web predeterminadas permiten el acceso anónimo a las páginas principales. Para probar Identity, agregue [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()
        {
        }
    }
}

Si ha iniciado sesión, cierre la sesión. Ejecute la aplicación y seleccione el vínculo Privacy. Se le redirige a la página de inicio de sesión.

Explorar Identity

Para explorar Identity con más detalle:

Identity Componentes

Todos los Identitypaquetes NuGet dependientes se incluyen en el marco compartido de ASP.NET Core.

El paquete principal de Identity es Microsoft.AspNetCore.Identity. Este paquete contiene el conjunto básico de interfaces para ASP.NET Core Identity, y está incluido por Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migración a ASP.NET Core Identity

Para obtener más información e instrucciones sobre cómo migrar el almacén existente Identity , consulte Migración de la autenticación y Identity.

Establecimiento de la seguridad de la contraseña

Consulte Configuración para obtener un ejemplo que establezca los requisitos mínimos de contraseña.

Impedir la publicación de recursos estáticos Identity

Para evitar la publicación de recursos estáticos Identity (hojas de estilos y archivos de JavaScript para la interfaz de usuario de Identity) en la raíz web, agregue la siguiente propiedad ResolveStaticWebAssetsInputsDependsOn y el destino RemoveIdentityAssets al archivo de proyecto de la aplicación:

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

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

Pasos siguientes