Scaffolding de Identity en proyectos de ASP.NET Core

Por Rick Anderson

ASP.NET Core proporciona ASP.NET Core Identity como una biblioteca de clases de Razor. Las aplicaciones que incluyen Identity pueden aplicar el proveedor de scaffolding para agregar de forma selectiva el código fuente incluido en la biblioteca de clases de Razor (RCL) de Identity. Puede que quiera generar código fuente que le permita modificar un código y cambiar el comportamiento; así, por ejemplo, podría indicar al proveedor de scaffolding que generara el código que se usa en el registro. El código generado tiene prioridad sobre el mismo código de la RCL de Identity. Para obtener el control total de la interfaz de usuario y no utilizar la RCL predeterminada, consulte la sección Creación de origen de interfaz de usuario de Identity completa.

Las aplicaciones que no incluyen autenticación pueden aplicar el proveedor de scaffolding para agregar el paquete de Identity de la RCL. Tiene la opción de seleccionar el código de Identity que se va a generar.

Aunque el proveedor de scaffolding genera la mayor parte del código necesario, debe actualizar el proyecto para completar el proceso. Este documento explica los pasos necesarios para completar una actualización de scaffolding de Identity.

Recomendamos utilizar un sistema de control de código fuente que muestre las diferencias entre archivos y permita dar marcha atrás en los cambios. Inspeccione los cambios después de ejecutar el proveedor de scaffolding de Identity.

Los servicios son necesarios cuando se usan Autenticación de dos factores, Confirmación de cuenta y recuperación de contraseña y otras características de seguridad con Identity. Los servicios o códigos auxiliares de servicio no se generan al aplicar scaffolding a Identity. Los servicios para habilitar estas características deben agregarse manualmente. Por ejemplo, consulte Requerir confirmación por correo electrónico.

Normalmente, las aplicaciones creadas con cuentas individuales no deben crear un nuevo contexto de datos.

Scaffolding de Identity en un proyecto de Razor sin autorización existente

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Migraciones, UseAuthentication y diseño

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Cambios de diseño

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de diseño:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Scaffolding de Identity en un proyecto de Razor con autorización

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Scaffolding de Identity en un proyecto de MVC sin autorización existente

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de Views/Shared/_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Agregue MapRazorPages a Program.cs como se muestra en el siguiente código resaltado:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.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.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

Scaffolding de Identity en un proyecto de MVC con autorización

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Aplicaciones Blazor del lado del cliente

Las aplicaciones de Blazor del lado del cliente usan sus propios métodos de interfaz de usuario de Identity y no pueden usar el scaffolding de Identity de ASP.NET Core.

Las aplicaciones de ASP.NET Core pueden seguir las instrucciones de Razor Pages/MVC de este artículo y se configuran igual que cualquier otro tipo de aplicación de ASP.NET Core compatible con Identity. El Blazor marco usa Razor versiones de componentes (.razor) de páginas de interfaz de Identity usuario (.cshtml) al aplicar scaffolding Identity a una Blazor aplicación web.

Para más información, consulte los artículos de Seguridad y Blazor de Identity.

Creación de un origen de interfaz de usuario de Identity completo

Para mantener el control total de la interfaz de usuario de Identity, ejecute el proveedor de scaffolding de Identity y seleccione Invalidar todos los archivos.

Configuración de la contraseña

Si las PasswordOptions están configuradas en Startup.ConfigureServices, es posible que se requiera la configuración del atributo [StringLength] para la propiedad Password en las páginas Identity de scaffolding. Las propiedades de InputModelPassword se encuentran en los archivos siguientes:

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

Deshabilitar una página

En esta sección se muestra cómo deshabilitar la página de registro, pero el enfoque se puede usar para deshabilitar cualquier página.

Para deshabilitar el registro de usuarios:

  • Aplique scaffolding a Identity. Incluya Account.Register, Account.Login y Account.RegisterConfirmation. Por ejemplo:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml.cs para que los usuarios no puedan registrarse desde este punto de conexión:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml para ser coherente con los cambios anteriores:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Comente o elimine el vínculo de registro de Areas/Identity/Pages/Account/Login.cshtml

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Actualice la página Areas/Identity/Pages/Account/RegisterConfirmation .

    • Quite el código y los vínculos del archivo cshtml.
    • Quite el código de confirmación de PageModel:
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

Uso de otra aplicación para agregar usuarios

Proporcione un mecanismo para agregar usuarios fuera de la aplicación web. Entre las opciones para agregar usuarios se incluyen:

  • Una aplicación web de administración dedicada.
  • Una aplicación de consola.

En el código siguiente se describe un enfoque para agregar usuarios:

  • Una lista de usuarios se lee en la memoria.
  • Se genera una contraseña única segura para cada usuario.
  • El usuario se agrega a la base de datos de Identity.
  • Se notifica al usuario y se le indica que cambie la contraseña.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

En el código siguiente se describe cómo agregar un usuario:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

Se puede seguir un enfoque similar para escenarios de producción.

Impedir la publicación de recursos estáticos de Identity

Para evitar la publicación de recursos estáticos de Identity en la raíz de la web, consulte Introducción a Identity en ASP.NET Core.

ASP.NET Core proporciona ASP.NET Core Identity como una biblioteca de clases de Razor. Las aplicaciones que incluyen Identity pueden aplicar el proveedor de scaffolding para agregar de forma selectiva el código fuente incluido en la biblioteca de clases de Razor (RCL) de Identity. Puede que quiera generar código fuente que le permita modificar un código y cambiar el comportamiento; así, por ejemplo, podría indicar al proveedor de scaffolding que generara el código que se usa en el registro. El código generado tiene prioridad sobre el mismo código de la RCL de Identity. Para obtener el control total de la interfaz de usuario y no utilizar la RCL predeterminada, consulte la sección Creación de origen de interfaz de usuario de Identity completa.

Las aplicaciones que no incluyen autenticación pueden aplicar el proveedor de scaffolding para agregar el paquete de Identity de la RCL. Tiene la opción de seleccionar el código de Identity que se va a generar.

Aunque el proveedor de scaffolding genera la mayor parte del código necesario, debe actualizar el proyecto para completar el proceso. Este documento explica los pasos necesarios para completar una actualización de scaffolding de Identity.

Recomendamos utilizar un sistema de control de código fuente que muestre las diferencias entre archivos y permita dar marcha atrás en los cambios. Inspeccione los cambios después de ejecutar el proveedor de scaffolding de Identity.

Los servicios son necesarios cuando se usan Autenticación de dos factores, Confirmación de cuenta y recuperación de contraseña y otras características de seguridad con Identity. Los servicios o códigos auxiliares de servicio no se generan al aplicar scaffolding a Identity. Los servicios para habilitar estas características deben agregarse manualmente. Por ejemplo, consulte Requerir confirmación por correo electrónico.

Normalmente, las aplicaciones creadas con cuentas individuales no deben crear un nuevo contexto de datos.

Scaffolding de Identity en un proyecto de Razor sin autorización existente

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Migraciones, UseAuthentication y diseño

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Cambios de diseño

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de diseño:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Scaffolding de Identity en un proyecto de Razor con autorización

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Scaffolding de Identity en un proyecto de MVC sin autorización existente

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de Views/Shared/_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Agregue MapRazorPages a Program.cs como se muestra en el siguiente código resaltado:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.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.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

Scaffolding de Identity en un proyecto de MVC con autorización

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Aplicar scaffolding Identity en una aplicación de Blazor del lado del servidor con autorización

Instale el paquete NuGet Microsoft.VisualStudio.Web.CodeGeneration.Design.

Nota

Para obtener instrucciones sobre cómo agregar paquetes a aplicaciones .NET, consulte los artículos de Instalación y administración de paquetes en Flujo de trabajo de consumo de paquetes (NuGet documentación). Confirme las versiones correctas del paquete en NuGet.org.


Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Migraciones

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Puntos de conexión de autenticación de estilo

Debido a que las aplicaciones de Blazor del lado del servidor usan páginas Razor Pages Identity, el estilo de la interfaz de usuario varía cuando un visitante navega entre componentes y páginas Identity. Tiene dos opciones para abordar los estilos incongruentes:

Componentes de Identity personalizados

ASP.NET Core Identity está diseñado para funcionar en el contexto de la comunicación de solicitud y respuesta HTTP, que no es el principal modelo de comunicación cliente-servidor en aplicaciones de Blazor. ASP.NET Aplicaciones principales que usan ASP.NET Core Identity para la administración de usuarios deben usar Razor Pages en lugar de componentes de Razor para Identityinterfaz de usuario relacionada, como el registro de usuarios, el inicio de sesión, el cierre de sesión y otras tareas de administración de usuarios.

Dado que SignInManager<TUser> y UserManager<TUser> no son compatibles en componentes de Razor, recomendamos usar la API web para administrar acciones de Identity desde componentes de Razor a través de una aplicación de ASP.NET Core del lado del servidor habilitada para Identity. Para obtener orientación sobre la creación de API web para aplicaciones de Blazor, consulte Llamar a una API web desde una aplicación de Blazor de ASP.NET Core.

Una forma de usar componentes de Razor para páginas de Identity en lugar de Razor es compilar sus propios componentes personalizados de IdentityRazor, pero Microsoft no recomienda ni brinda soporte para este método. Para obtener contexto adicional, explore las conversaciones siguientes. En las siguientes conversaciones, los ejemplos de código en los comentarios de las incidencias y los ejemplos de código con vínculos cruzados en repositorios de GitHub ajenos a Microsoft no cuentan con el soporte de Microsoft, pero podrían ser útiles para algunos desarrolladores:

Para obtener ayuda adicional al buscar componentes personalizados de IdentityRazor o buscar componentes de terceros de Razor, se recomiendan los siguientes recursos:

Uso de un diseño personalizado con estilos de aplicación de Blazor

El diseño y los estilos de las páginas de Identity pueden modificarse para producir páginas que usen estilos similares al tema predeterminado de Blazor. Este enfoque no está cubierto por la documentación.

Aplicaciones Blazor del lado del cliente

Las aplicaciones de Blazor del lado del cliente usan sus propios métodos de interfaz de usuario de Identity y no pueden usar el scaffolding de Identity de ASP.NET Core. Las aplicaciones de ASP.NET Core del lado del servidor de soluciones de Blazor hospedadas pueden seguir las instrucciones de Razor Pages/MVC de este artículo y se configuran igual que cualquier otro tipo de aplicación de ASP.NET Core compatible con Identity.

El marco de trabajo de Blazor no incluye Razor versiones de componentes de páginas de interfaz de usuario de Identity. Los componentes de la interfaz de usuario de Razor de Identity pueden compilarse a medida u obtenerse de orígenes de terceros no compatibles.

Para más información, consulte los artículos de Seguridad y Blazor de Identity.

Creación de un origen de interfaz de usuario de Identity completo

Para mantener el control total de la interfaz de usuario de Identity, ejecute el proveedor de scaffolding de Identity y seleccione Invalidar todos los archivos.

Configuración de la contraseña

Si las PasswordOptions están configuradas en Startup.ConfigureServices, es posible que se requiera la configuración del atributo [StringLength] para la propiedad Password en las páginas Identity de scaffolding. Las propiedades de InputModelPassword se encuentran en los archivos siguientes:

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

Deshabilitar una página

En esta sección se muestra cómo deshabilitar la página de registro, pero el enfoque se puede usar para deshabilitar cualquier página.

Para deshabilitar el registro de usuarios:

  • Aplique scaffolding a Identity. Incluya Account.Register, Account.Login y Account.RegisterConfirmation. Por ejemplo:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml.cs para que los usuarios no puedan registrarse desde este punto de conexión:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml para ser coherente con los cambios anteriores:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Comente o elimine el vínculo de registro de Areas/Identity/Pages/Account/Login.cshtml

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Actualice la página Areas/Identity/Pages/Account/RegisterConfirmation .

    • Quite el código y los vínculos del archivo cshtml.
    • Quite el código de confirmación de PageModel:
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

Uso de otra aplicación para agregar usuarios

Proporcione un mecanismo para agregar usuarios fuera de la aplicación web. Entre las opciones para agregar usuarios se incluyen:

  • Una aplicación web de administración dedicada.
  • Una aplicación de consola.

En el código siguiente se describe un enfoque para agregar usuarios:

  • Una lista de usuarios se lee en la memoria.
  • Se genera una contraseña única segura para cada usuario.
  • El usuario se agrega a la base de datos de Identity.
  • Se notifica al usuario y se le indica que cambie la contraseña.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

En el código siguiente se describe cómo agregar un usuario:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

Se puede seguir un enfoque similar para escenarios de producción.

Impedir la publicación de recursos estáticos de Identity

Para evitar la publicación de recursos estáticos de Identity en la raíz de la web, consulte Introducción a Identity en ASP.NET Core.

ASP.NET Core proporciona ASP.NET Core Identity como una biblioteca de clases de Razor. Las aplicaciones que incluyen Identity pueden aplicar el proveedor de scaffolding para agregar de forma selectiva el código fuente incluido en la biblioteca de clases de Razor (RCL) de Identity. Puede que quiera generar código fuente que le permita modificar un código y cambiar el comportamiento; así, por ejemplo, podría indicar al proveedor de scaffolding que generara el código que se usa en el registro. El código generado tiene prioridad sobre el mismo código de la RCL de Identity. Para obtener el control total de la interfaz de usuario y no utilizar la RCL predeterminada, consulte la sección Creación de origen de interfaz de usuario de Identity completa.

Las aplicaciones que no incluyen autenticación pueden aplicar el proveedor de scaffolding para agregar el paquete de Identity de la RCL. Tiene la opción de seleccionar el código de Identity que se va a generar.

Aunque el proveedor de scaffolding genera la mayor parte del código necesario, debe actualizar el proyecto para completar el proceso. Este documento explica los pasos necesarios para completar una actualización de scaffolding de Identity.

Recomendamos utilizar un sistema de control de código fuente que muestre las diferencias entre archivos y permita dar marcha atrás en los cambios. Inspeccione los cambios después de ejecutar el proveedor de scaffolding de Identity.

Los servicios son necesarios cuando se usan Autenticación de dos factores, Confirmación de cuenta y recuperación de contraseña y otras características de seguridad con Identity. Los servicios o códigos auxiliares de servicio no se generan al aplicar scaffolding a Identity. Los servicios para habilitar estas características deben agregarse manualmente. Por ejemplo, consulte Requerir confirmación por correo electrónico.

Al aplicar scaffolding a Identity con un nuevo contexto de datos en un proyecto con cuentas individuales existentes:

  • En Startup.ConfigureServices, quite las llamadas a:
    • AddDbContext
    • AddDefaultIdentity

Por ejemplo, AddDbContext y AddDefaultIdentity se comentan en el código siguiente:

public void ConfigureServices(IServiceCollection services)
{
    //services.AddDbContext<ApplicationDbContext>(options =>
    //    options.UseSqlServer(
    //        Configuration.GetConnectionString("DefaultConnection")));
    //services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    //    .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddControllersWithViews();
    services.AddRazorPages();
}

El código anterior comenta el código que está duplicado en Areas/Identity/IdentityHostingStartup.cs

Normalmente, las aplicaciones creadas con cuentas individuales no deben crear un nuevo contexto de datos.

Scaffolding de Identity en un proyecto vacío

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Actualice la clase de Startup con un código similar al siguiente:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

Se recomienda UseHsts, pero no es necesario. Para más información, consulte Protocolo de seguridad de transporte estricto HTTP.

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Scaffolding de Identity en un proyecto de Razor sin autorización existente

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Identity está configurado en Areas/Identity/IdentityHostingStartup.cs. Para más información, vea IHostingStartup.

Migraciones, UseAuthentication y diseño

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Enable authentication (Habilitar autenticación)

Actualice la clase de Startup con un código similar al siguiente:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

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

Se recomienda UseHsts, pero no es necesario. Para más información, consulte Protocolo de seguridad de transporte estricto HTTP.

Cambios de diseño

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de diseño:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

Scaffolding de Identity en un proyecto de Razor con autorización

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Algunas opciones de Identity están configuradas en Areas/Identity/IdentityHostingStartup.cs. Para más información, vea IHostingStartup.

Scaffolding de Identity en un proyecto de MVC sin autorización existente

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Opcional: agregue el inicio de sesión parcial (_LoginPartial) al archivo de Views/Shared/_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>
  • Mueva el archivo Pages/Shared/_LoginPartial.cshtml a Views/Shared/_LoginPartial.cshtml

Identity está configurado en Areas/Identity/IdentityHostingStartup.cs. Para más información, vea IHostingStartup.

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Actualice la clase de Startup con un código similar al siguiente:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

Se recomienda UseHsts, pero no es necesario. Para más información, consulte Protocolo de seguridad de transporte estricto HTTP.

Scaffolding de Identity en un proyecto de MVC con autorización

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Aplicar scaffolding Identity en una aplicación de Blazor sin autorización existente

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Identity está configurado en Areas/Identity/IdentityHostingStartup.cs. Para obtener más información, vea IHostingStartup.

Migraciones

El código de base de datos generado Identity requiere migraciones de Entity Framework Core. Si no se ha creado ni aplicado una migración para crear el esquema Identity a la base de datos, cree una migración y actualice la base de datos. Por ejemplo, ejecute los siguientes comandos:

En la Consola del administrador de paquetes de Visual Studio:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

El parámetro de nombre "CreateIdentitySchema" para el comando Add-Migration es arbitrario. "CreateIdentitySchema" describe la migración.

Si el esquema Identity ya se ha creado pero no se ha aplicado a la base de datos, solo se debe ejecutar el comando para actualizar la base de datos:

En la Consola del administrador de paquetes de Visual Studio, ejecute Update-Database:

Update-Database

Puede confirmar la aplicación de un esquema Identity con el siguiente comando. La salida del comando incluye una columna "applied" para mostrar qué migraciones se aplican a la base de datos.

En la Consola del administrador de paquetes de Visual Studio, ejecute Get-Migration:

Get-Migration

Si existe más de un contexto de base de datos, especifique el contexto con el parámetro -Context.

Puntos de conexión de autenticación de estilo

Debido a que las aplicaciones de Blazor del lado del servidor usan páginas Razor Pages Identity, el estilo de la interfaz de usuario varía cuando un visitante navega entre componentes y páginas Identity. Tiene dos opciones para abordar los estilos incongruentes:

Componentes de Identity personalizados

Un enfoque para usar componentes para Identity en lugar de páginas consiste en compilar componentes de Identity. Dado que SignInManager y UserManager no son compatibles en componentes de Razor, use puntos de conexión de la API web en la aplicación de Blazor para procesar las acciones de la cuenta de usuario.

Uso de un diseño personalizado con estilos de aplicación de Blazor

El diseño y los estilos de las páginas de Identity pueden modificarse para producir páginas que usen estilos similares al tema predeterminado de Blazor. Este enfoque no está cubierto por la documentación.

Aplicar scaffolding Identity en una aplicación de Blazor del lado del servidor con autorización

Ejecute el proveedor de scaffolding Identity:

  • En Explorador de soluciones, haga clic con el botón derecho en el proyecto >Agregar>Nuevo elemento con scaffolding.
  • En el panel izquierdo del cuadro de diálogo Agregar nuevo elemento con scaffolding, seleccione Identity. Seleccione Identity en el panel central. Seleccione el botón Agregar.
  • En el cuadro de diálogo Agregar Identity, seleccione las opciones que desee.
    • Si tiene una página de diseño personalizada existente para Identity (_Layout.cshtml), seleccione la página de diseño existente para evitar sobrescribir el diseño con marcado incorrecto por el proveedor de scaffolding. Por ejemplo, seleccione:
      • Pages/Shared/_Layout.cshtml para Razor Pages o proyectos de Blazor Server con infraestructura de Razor Pages existente.
      • Views/Shared/_Layout.cshtml para proyectos MVC o proyectos de Blazor Server con infraestructura de MVC existente.
    • Para el contexto de datos (clase DbContext):
      • Seleccione la clase de contexto de datos. Debe seleccionar al menos un archivo para agregar el contexto de datos.
      • Para crear un contexto de datos y posiblemente crear una nueva clase de usuario para Identity, seleccione el botón +. Acepte el valor predeterminado o especifique una clase (por ejemplo, Contoso.Data.ApplicationDbContext para una empresa denominada "Contoso"). Para crear una nueva clase de usuario, seleccione el botón + para Clase de usuario y especifique la clase (por ejemplo, ContosoUser para una empresa llamada "Contoso").
    • Seleccione el botón Agregar para ejecutar el proveedor de scaffolding.

Algunas opciones de Identity están configuradas en Areas/Identity/IdentityHostingStartup.cs. Para más información, vea IHostingStartup.

Aplicaciones Blazor del lado del cliente

Las aplicaciones de Blazor del lado del cliente usan sus propios métodos de interfaz de usuario de Identity y no pueden usar el scaffolding de Identity de ASP.NET Core. Las aplicaciones de ASP.NET Core del lado del servidor de soluciones de Blazor hospedadas pueden seguir las instrucciones de Razor Pages/MVC de este artículo y se configuran igual que cualquier otro tipo de aplicación de ASP.NET Core compatible con Identity.

El marco de trabajo de Blazor no incluye Razor versiones de componentes de páginas de interfaz de usuario de Identity. Los componentes de la interfaz de usuario de Razor de Identity pueden compilarse a medida u obtenerse de orígenes de terceros no compatibles.

Para más información, consulte los artículos de Seguridad y Blazor de Identity.

Creación de un origen de interfaz de usuario de Identity completo

Para mantener el control total de la interfaz de usuario de Identity, ejecute el proveedor de scaffolding de Identity y seleccione Invalidar todos los archivos.

El siguiente código resaltado muestra los cambios para reemplazar la interfaz de usuario de Identity predeterminada por Identity en una aplicación web de ASP.NET Core 2.1. Es posible que quiera hacer esto para tener un control total de la interfaz de usuario de Identity.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<IdentityUser, IdentityRole>()
        // services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
    });

    // using Microsoft.AspNetCore.Identity.UI.Services;
    services.AddSingleton<IEmailSender, EmailSender>();
}

El valor predeterminado Identity se reemplaza en el código siguiente:

services.AddIdentity<IdentityUser, IdentityRole>()
    // services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

El siguiente código establece LoginPath, LogoutPath y AccessDeniedPath):

services.ConfigureApplicationCookie(options =>
{
    options.LoginPath = $"/Identity/Account/Login";
    options.LogoutPath = $"/Identity/Account/Logout";
    options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});

Registre una implementación de IEmailSender, por ejemplo:

// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
public class EmailSender : IEmailSender
{
    public Task SendEmailAsync(string email, string subject, string message)
    {
        return Task.CompletedTask;
    }
}

Configuración de la contraseña

Si las PasswordOptions están configuradas en Startup.ConfigureServices, es posible que se requiera la configuración del atributo [StringLength] para la propiedad Password en las páginas Identity de scaffolding. Las propiedades de InputModelPassword se encuentran en los archivos siguientes:

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

Deshabilitar una página

En esta sección se muestra cómo deshabilitar la página de registro, pero el enfoque se puede usar para deshabilitar cualquier página.

Para deshabilitar el registro de usuarios:

  • Aplique scaffolding a Identity. Incluya Account.Register, Account.Login y Account.RegisterConfirmation. Por ejemplo:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml.cs para que los usuarios no puedan registrarse desde este punto de conexión:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • Actualice Areas/Identity/Pages/Account/Register.cshtml para ser coherente con los cambios anteriores:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • Comente o elimine el vínculo de registro de Areas/Identity/Pages/Account/Login.cshtml

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • Actualice la página Areas/Identity/Pages/Account/RegisterConfirmation .

    • Quite el código y los vínculos del archivo cshtml.
    • Quite el código de confirmación de PageModel:
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

Uso de otra aplicación para agregar usuarios

Proporcione un mecanismo para agregar usuarios fuera de la aplicación web. Entre las opciones para agregar usuarios se incluyen:

  • Una aplicación web de administración dedicada.
  • Una aplicación de consola.

En el código siguiente se describe un enfoque para agregar usuarios:

  • Una lista de usuarios se lee en la memoria.
  • Se genera una contraseña única segura para cada usuario.
  • El usuario se agrega a la base de datos de Identity.
  • Se notifica al usuario y se le indica que cambie la contraseña.
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

En el código siguiente se describe cómo agregar un usuario:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

Se puede seguir un enfoque similar para escenarios de producción.

Impedir la publicación de recursos estáticos de Identity

Para evitar la publicación de recursos estáticos de Identity en la raíz de la web, consulte Introducción a Identity en ASP.NET Core.

Recursos adicionales