Documentos de Académico
Documentos de Profesional
Documentos de Cultura
En esta práctica se muestra cómo crear una aplicación web ASP.NET Core con datos de usuario protegidos por
autorización. Se usará el modelo “Alumnos” de la práctica pasada y un nuevo modelo “Contactos”, esto con la finalidad
de representar los pasos para proteger cada una de las páginas y directorios.
Para poder realizarla, se necesita implementar Identity en ASP.NET Core, la cual tiene las siguientes caracteristicas:
Es una API que admite la funcionalidad de inicio de sesión de la interfaz de usuario (UI).
Administra usuarios, contraseñas, datos de perfil, roles, notificaciones, tokens, confirmación por correo
electrónico, etc.
Los usuarios pueden crear una cuenta con la información de inicio de sesión almacenada en Identity o pueden usar un
proveedor de inicio de sesión externo. Los proveedores de inicios de sesión externos admitidos incluyen cuentas de
Facebook, Google, Microsoft y Twitter.
Identity normalmente se configura mediante una base de datos SQL Server para almacenar nombres de usuario,
contraseñas y datos de perfil. Como alternativa, se puede usar otro almacén persistente, por ejemplo, Azure Table
Storage.
Para ambos modelos se mostrar una lista de alumnos (en la raíz del proyecto) y de contactos (en un subdirectorio) que
han creado los usuarios autenticados (registrados). Hay tres grupos de seguridad:
Los usuarios registrados (Sin rol, pero se puede considerar como Rol Users) pueden ver todos los datos
aprobados en el modelo “Contactos” y pueden editar o eliminar sus propios datos. En el modelo Alumnos solo
pueden ver todos los datos.
Los Gerentes (Rol Manager) pueden aprobar o rechazar los datos de contacto. Solo los contactos aprobados son
visibles para los usuarios. También pueden modificar la información de los Alumnos
Los Administradores (Rol Administrator) pueden aprobar, rechazar y editar o eliminar los datos. El
administrador tiene todos los privilegios. Puede leer, editar o eliminar cualquier contacto, alumno y cambiar el
estado de los contactos.
Como nota inicial, este proyecto también se realizará con la ideología Code First.
Al abrir Visual Studio, aparecerá la siguiente pantalla donde se debe elegir “Crear un proyecto”:
Se elegirá “Aplicación web ASP.NET Core”
Crearemos una “Aplicación web” simple sin MVC aunque seguiremos muchas convenciones.
Cabe mencionar que a diferencia del proyecto anterior aquí ocuparemos Autenticación por “cuentas individuales”.
El proyecto generado proporciona ASP.NET Core Identity como biblioteca Razor de clases. La biblioteca de clases
IdentityRazor expone puntos de conexión con el área Identity. Por ejemplo:
/Identity/Account/Login
/Identity/Account/Logout
/Identity/Account/Manage
Las aplicaciones .NET Core, como ya se mencionó anteriormente, no usan el framework .NET completo, solo módulos o
partes administradas por Nuget.
En el proyecto anterior, no había paquetes agregados desde la creación, en cambio en este proyecto con autenticación
si se pueden observar varios paquetes instalados desde la creación del proyecto:
Para esta práctica es necesario agregar los siguientes módulos:
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Desginer
Para ello, en el menú Herramientas, se debe acceder a la opción Administrador de paquetes NuGet, y en el menú que
se desplegara, elegir: Administrar paquetes NuGet para la solución.
Escriban los paquetes (se listan arriba) a descargar, en la imagen se muestran los 3, deben instalar uno a la vez, en el
recuadro de la derecha por cada paquete marquen el proyecto y procedan con el botón Instalar. Miren la nota en la
siguiente página.
En cada paquete les pedirá aceptar la licencia de módulos.
Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Design
Primeros pasos:
Como ya se habló antes, las aplicaciones Code First, implican que la base de datos se creara en función del código y no al
revés, por lo tanto debemos iniciar con la creación de una cadena de conexión, para ello editaremos el archivo
“appsettings.json” y como se vio en la práctica anterior, se debe agregar una cadena de conexión.
Para poder usar SQL Server, se modificarán los datos del manejador y la base de datos:
Cabe mencionar que la cadena JSON llamada Conexión contiene los siguientes valores:
Modelos
Sobre el proyecto, presionar clic derecho y en la opción Agregar, desplegar el submenú y seleccionar Nueva Carpeta.
Contextos
Cada Modelo debe contar con un Contexto de Base de datos, Estos contextos no hay ninguna regla que defina su
ubicación, pero para este tipo de proyectos ya está creado un contexto, con una migración (esta migración es de
identity) en una carpeta para los Contextos de base de datos llamada Data.
Antes de continuar, se deben crear las tablas de identity Framework, por lo tanto, en la consola de Nuget se debe
ejecutar:
Una instancia DbContext representa una combinación de una unidad de trabajo y un reposito de patterns los cuales pueden ser
usados para realizar querys a una tabla en la base de datos definida en alguna cadena de conexión ( get), así mismo también se
pueden escribir datos y realizar cambios (set).
Controladores de Autenticación.
Para implementarlos se debe crear una nueva carpeta en la raíz del proyecto
En esta clase se definen las acciones a realizar por cada rol y algunas por modelos, solo como etiquetas.
Authorization/Operations.cs
Authorization/ContactosAdministratorsAuthorizationHandler.cs
Authorization/ContactosIsOwnerAuthorizationHandler.cs
Authorization/ContactosManagerAuthorizationHandler.cs
Authorization/AlumnosAdministratorAuthorizationHandler.cs
Authorization/AlumnosIsOwnerAuthorizationHandler.cs
Authorization/AlumnosManagerAuthorizationHandler.cs
Configuración de la cuenta de prueba
Se debe crear una clase SeedData, la cual crea dos cuentas: Administrator y Manager.
Antes de crear esta clase, se debe usar la herramienta Administrador de secretos para establecer una contraseña para
estas cuentas. Para ello sobre el proyecto, se debe presionar el botón derecho del mouse y elegir: Abrir en Terminal
Esto abrirá una consola powershell para desarrolladores, en la cual se debe agregar a los secretos de usuario una
contraseña compleja, esa contraseña debe ser por lo menos de 8 caracteres, con mayusculas, minúsculas, números y
símbolos, se usará para crear los usuarios iniciales, en este caso se usará “NETC0re*”, pero pueden usar la que gusten,
solo no la olviden, esto se realizara con el comando:
using CoreRazorUsers.Authorization;
using CoreRazorUsers.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace CoreRazorUsers.Data
{
public static class SeedData {
public static async Task Initialize(IServiceProvider serviceProvider, string testUserPw) {
using (var context = new ApplicationDbContext(serviceProvider.GetRequiredService<DbContextOptions<ApplicationDbContext>>())) {
// For sample purposes seed both with the same password.
// Password is set with the following:
// dotnet user-secrets set SeedUserPW <pw>
// allowed user can create and edit contacts that they create
var managerID = await EnsureUser(serviceProvider, testUserPw, "manager@net.com");
await EnsureRole(serviceProvider, managerID, Constants.ContactosManagersRole);
await EnsureRole(serviceProvider, managerID, Constants.AlumnosManagersRole);
SeedDB(context, adminID);
SeedDB(context, managerID);
SeedDB(context, userID);
}
}
private static async Task<string> EnsureUser(IServiceProvider serviceProvider, string testUserPw, string UserName) {
var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();
if (user == null) {
throw new Exception("No es una contrasea fuerte!");
}
return user.Id;
}
private static async Task<IdentityResult> EnsureRole(IServiceProvider serviceProvider, string uid, string role) {
var roleManager = serviceProvider.GetService<RoleManager<IdentityRole>>();
if (roleManager == null) {
throw new Exception("roleManager null");
}
IdentityResult IR;
if (!await roleManager.RoleExistsAsync(role)) {
IR = await roleManager.CreateAsync(new IdentityRole(role));
}
if (user == null) {
throw new Exception("The testUserPw password was probably not strong enough!");
}
context.Alumnos.AddRange(
new Alumnos
{
NC = "00000001",
Nombre = "Alumno 1",
DeudaBiblioteca = 10,
Promedio = 90.1f,
Inscrito = AlumnoStatus.Inscrito,
OwnerID = adminID
},
new Alumnos
{
NC = "00000002",
Nombre = "Alumno 2",
DeudaBiblioteca = 11,
Promedio = 91.1f,
Inscrito = AlumnoStatus.Inscrito,
OwnerID = adminID
},
new Alumnos
{
NC = "00000003",
Nombre = "Alumno 3",
DeudaBiblioteca = 13,
Promedio = 93.1f,
Inscrito = AlumnoStatus.Inscrito,
OwnerID = adminID
},
new Alumnos
{
NC = "00000004",
Nombre = "Alumno 4",
DeudaBiblioteca = 14,
Promedio = 40.1f,
Inscrito = AlumnoStatus.Inscrito,
OwnerID = adminID
},
new Alumnos
{
NC = "00000005",
Nombre = "Alumno 5",
DeudaBiblioteca = 15,
Promedio = 90.5f,
Inscrito = AlumnoStatus.Inscrito,
OwnerID = adminID
}
);
context.SaveChanges();
}
}
}
}
Configurar Identity
En este tópico, migración se refiere a crear los objetos en el manejador de base de datos desde Los modelos Alumnos y
Contactos.
Para crear los objetos en la Base de Datos, se debe crear una migración desde la “Consola del Administrador de
paquetes”, para ello se debe desplegar el menú Herramientas, elegir la opción “Administrador de paquetes NuGet” y
del submenú elegir “Consola del Administrador de paquetes”.
add-migration MigracionModelos
Esto creara una nueva migración dentro de la carpeta Data/Migrations, con algunos archivos, como se muestra en la
siguiente imagen.
Como un punto extra, en esta migración se agregaran índices únicos para evitar crearlos por código:
Una base de datos llamada CoreRazorUsers con una tabla llamada Alumnos y otra tabla llamada Contactos, las cuales
contienen los campos definidos en el modelo y sus datos iniciales