Saltar al contenido

Configurar la identidad ASP.NET con un enfoque de código primero

La siguiente parte de la configuración de nuestra capa API será incluir diferentes roles en nuestra aplicación. De nuevo, usaremos el paquete de identidad con el contexto de BD personalizado que hemos creado. Mientras que los usuarios son manejados por el ApplicationUserManager, los roles son manejados por el ApplicationRoleManager.

Esta vez la clase y sus referencias no están andadas por la plantilla y debemos incluirlas escribiendo un poco de código. Pero antes de ir a este paso, vamos a registrar un primer usuario en nuestro sistema.

Configurar la identidad ASP.NET con un enfoque de código primero
Configurar la identidad ASP.NET con un enfoque de código primero

Registro de usuarios

Dirige el proyecto. En la documentación de nuestra API, ya tenemos todos los puntos finales del andamiaje del Controlador de Cuentas

Open Postman o cualquier herramienta que utilice para hacer peticiones.

Siguiendo la documentación, debemos pasar el formato JSON de muestra cuando hacemos una solicitud de registro de un usuario. Al hacer la solicitud, asegúrese de poner el puerto exacto de LocalDb. Esta solicitud debe devolver una respuesta de 200OK y crear las tablas apropiadas en nuestra base de datos insertando los nuevos datos en ellas.

Estamos listos para abrir la base de datos y continuar.

Observamos que se crearon algunas tablas porque cuando hicimos la solicitud primero se ejecutó una migración y luego nuestros datos de usuario se almacenaron en la tabla dbo.AspNetUsers. Como ya he mencionado, esta tabla sólo tiene las columnas por defecto de la clase IdentityUser. Las otras dos tablas que nos interesan son dbo.AspNetRoles y dbo.AspNetUserRoles. Como ya se deduce, la primera tabla servirá para almacenar todos los tipos de roles en nuestra aplicación. La segunda será la tabla de unión que define la relación de muchos a muchos entre los usuarios y los roles. Si no entiende los términos relacionados con SQL no se preocupe; el paquete Microsoft.AspNet.Identity que utilizamos se ocupa del uso adecuado de nuestra base de datos. Nuestro trabajo es configurar la aplicación ASP.NET, para que envíe los datos correctos a nuestra base de datos.

Para proceder, abriremos de nuevo nuestro proyecto de API y escribiremos algo de código para hacer uso de las tablas ya creadas.

Abra AppStartIdentityConfig.cs y coloque el siguiente fragmento después del final de la clase ApplicationUserManager.

123456789101112131415161718//// Resumen base(roleStore){}publicstaticApplicationRoleManagerCreate(IdentityFactoryOptions<ApplicationRoleManager,options,IOwinContext context){///Se basa en el mismo contexto que el ApplicationUserManagervar appRoleManager =newApplicationRoleManager(newRoleStore<IdentityRole Get<AppUsersDbContext;}));return appRoleManager;}}

csharp

Este código creará la clase ApplicationRoleManager que vamos a utilizar en nuestro Controlador de Cuenta cuando escribamos los puntos finales, que asignará roles a diferentes usuarios. Pero antes de sumergirnos en nuestro controlador, vamos a inicializar el ApplicationRoleManager de la misma manera que lo hicimos para nuestro ApplicationUserManager. Así que, abre el archivo AppStartStartup.Auth.cs y pon el siguiente código en el método ConfigureAuth:

12345678910publicvoidConfigureAuth(IAppBuilder app){// Configurar el contexto de la BBD y el gestor de usuarios para usar una sola instancia por solicitud app.CreatePerOwinContext(AppUsersDbContext.Create);///Iniciar la aplicación del gestor de usuarios. CreatePerOwinContext<ApplicationUserManager,Create)///Iniciando el Role Manager app.CreatePerOwinContext<ApplicationRoleManager,Create)///Resto del método... Asegúrate de no borrar nada, ya que está relacionado con la autorización basada en tokens que vamos a utilizar.}

csharp

Después de hacer esto, podemos abrir algunos puntos finales que se encargarán de asignar roles a los usuarios. Ve al archivo ControllersAccountController.cs y pon el siguiente fragmento en él:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051[AllowAnonymous][Route("users/{id: guid}/roles")][HttpPut]publicasync Task<IHttpActionResult>AssignRolesToUser(string id,string[] rolesToAssign){if(rolesToAssign ==null){regresa esto. BadRequest("No se especifican roles");}///encontrar el usuario al que queremos asignar los roles tovar appUser =awaitthis. UserManager.FindByIdAsync(id);if(appUser ==null|| appUser.IsDeleted){returnNotFound();}///check if the user currently has any rolesvar currentRoles =awaitthis.UserManager. GetRolesAsync(appUser.Id);var rolesNotExist = rolesToAssign.Except(this.RoleManager.Roles.Select(x => x.Name)).ToArray();if(rolesNotExist.Count()>0){ ModelState. AñadirModelError("",cadena.Formato("Los roles $0027{0}$0027 no existen en el sistema",cadena.Join(",", rolesNotExist)));devolver esto. BadRequest(ModelState);}/// remover el usuario de los roles actuales, si los hayIdentityResult removeResult =awaitthis.UserManager.RemoveFromRolesAsync(appUser.Id, currentRoles.ToArray());if(!removeResult.Succeeded){ ModelState. AddModelError("", "Failed to remove user roles");returnBadRequest(ModelState);}///asignar usuario a los nuevos rolesIdentityResult addResult =awaitthis.UserManager.AddToRolesAsync(appUser. Id, rolesToAssign);if(!addResult.Succeeded){ ModelState.AddModelError("", "Failed to add user roles");returnBadRequest(ModelState);}returnOk(new{ userId = id, rolesAssigned = rolesToAssign });}

csharp

La ruta para nuestro nuevo punto final será usuarios/{id:guid}/roles. Un ID y una serie de roles deberían ser los parámetros de la petición.

Finalmente, haga una instancia de nuestro ApplicationRoleManager. Para ello, añade este fragmento de código en el AccountController

12345678910111213141516171819202122232425262728controlador de cuentas de clase pública:ApiController{////...privateApplicationRoleManager _roleManager;///... publicAccountController(ApplicationUserManager userManager, ISecureDataFormat<AuthenticationTicket > accessTokenFormat,ApplicationRoleManager roleManager){///Make an instance of the user manager in the controller to avoid null reference exception UserManager = userManager; AccessTokenFormat = accessTokenFormat;///Make an instance of the role manager in the constructor to avoid null reference exception RoleManager = roleManager;}///. ..publicApplicationRoleManager RoleManager {get{return _roleManager ?? Request.GetOwinContext().GetUserManager<ApplicationRoleManager;();}privateset{ _roleManager =valor;}}/// Resto de la clase...}

csharp

Ahora, estamos listos para probar nuestro nuevo punto final usando la propiedad ID del usuario que acabamos de añadir.

Primero, agregue una entrada en su dbo.AspNetRoles, que contiene el nombre del nuevo rol. En nuestro caso, añadiremos tres de ellos: Admin, ShopManager y Seller. Abra su MSMS, y ejecute la siguiente consulta:

1234567891011121314INSERTINTO dbo.AspNetRoles(Id, Nombre)VALORES(1,$0027Admin$0027)INSERTINTO dbo.AspNetRoles(Id, Nombre)VALORES(2,$0027ShopManager$0027)INSERTINTO dbo.AspNetRoles(Id, Nombre)VALORES(3,$0027Vendedor$0027)

sql

Esto debería ser suficiente para que hagamos la petición.

Ahora tenemos la conexión en nuestra base de datos.

Hasta ahora, hemos desarrollado un sistema de cuentas de usuario completamente funcional que es capaz de mantener el registro de usuarios y diferentes funciones.

Añadir propiedades no predeterminadas a los usuarios

Ahora, vamos a añadir algunos campos adicionales a nuestro sistema de cuentas. Para mantener las cosas simples, crearé sólo dos columnas adicionales en la tabla de AspNetUsers. La primera será IsDeleted, una columna BIT que servirá como marcador para el borrado suave.

La segunda columna será CompanySecretCode, una columna cifrada que mantiene un código que cada usuario puede utilizar para acceder a diferentes documentos (no hay ninguna razón en particular para poner una columna de este tipo en nuestra tabla, es sólo un ejemplo de cómo cifrar columnas cuando se trata de un sistema de cuentas).

Borrado suave

En el borrado suave, marcamos una entidad como “borrada” pero no la eliminamos de la base de datos hasta que decidimos que es extraña.

Dado que el paquete que estamos usando implementa primero migraciones de código, basta con añadir la columna IsDeleted a nuestra clase ApplicationUser y luego definir claramente su valor por defecto y su uso posterior.Primero, abrir el archivo AppStartIdentityConfig.cs y añadir la propiedad:

123456789101112publicclassApplicationUser:IdentityUser{// La propiedad utilizada para el borrado suave de userspublicbool se borra {get;set;}publicasync Task<ClaimsIdentity>GenerateUserIdentityAsync(UserManager<ApplicationUser> manager,string authenticationType){// Nótese que el authenticationType debe coincidir con el definido en CookieAuthenticationOptions. AuthenticationTypevar userIdentity =await manager.CreateIdentityAsync(this, authenticationType);// Agregar usuario personalizado reclama herereturn userIdentity;}}

csharp

Después de esto, podemos empezar a usar nuestra nueva columna inmediatamente. Lo primero y más obvio es asignar un valor a esta propiedad cuando creamos el usuario. Para ello, sustituya el método de registro en el AccountController por el siguiente código:

123456789101112131415161718192021222324/// POST api/Account/Register[AllowAnonymous][Route("Register")]publicasync Task<IHttpActionResult>Register(RegisterBindingModel model){if(!ModelState.IsValid){returnBadRequest(ModelState);}var user =newApplicationUser(){ UserName = model. Email, Email = model.Email };//set the IsDeleted property to false user.IsDeleted =false;IdentityResult result =await UserManager.CreateAsync(user, model.Password);if(!result.Succeeded){returnGetErrorResult(result);}returnOk();}

csharp

Como hemos cambiado nuestra clase ApplicationUser por defecto y nuestra base de datos todavía no lo sabe, deberíamos ver una excepción cuando intentemos añadir un nuevo usuario. La excepción dice: “Considere el uso de Code First Migrations para actualizar la base de datos”.

Deberíamos ejecutar una migración que creará la columna “IsDeleted” en nuestra base de datos. Antes de hacer esto, eliminaremos el usuario que hemos creado porque no tiene la columna IsDeleted y esto va a ser un obstáculo cuando intentemos hacerla no anulable. Siguiente:

  1. Abre la consola del administrador de paquetes.
  2. Establezca la propiedad del Proyecto Predeterminado en WebApi.
  3. Habilitar las migraciones apuntando a nuestro contexto personalizado: Enable-Migrations -contexttypename AppUsersDbContext
  4. Añade una migración: Añadir una migración inicial
  5. Actualización de la base de datos

Estos comandos deben ejecutar una migración que cree la columna necesaria en la base de datos. Además, debería tener una nueva carpeta llamada Migraciones en su proyecto WebApi. Allí puedes ver todas las migraciones que has ejecutado y puedes escribir nuevas, en caso de que las necesites.

Este es el código de migración que usamos arriba:

1234567891011publicpartialclassInitial:DbMigration{publicoverridevoidUp(){AddColumn("dbo.AspNetUsers", "IsDeleted", c => c.Boolean(nullable:false));}publicoverridevoidDown(){}}

csharp

Ahora, estamos listos para crear nuestro nuevo usuario (sigue los mismos pasos que hemos usado para crear el anterior).

¡Voila! Tenemos nuestra columna “IsDeleted” como parte de nuestra entidad de usuario de la aplicación.