Estoy tratando de escribir una política personalizada para una aplicación web ASP.NET Core 3.1, usando un proveedor de almacenamiento de identidad personalizado.
Traté de entender el hecho de que las políticas en ASP.NET Core están diseñadas para tomar información del usuario de un HttpContext
objeto, cuando leí esto en un artículo de MSDN:
una vez que tenga una referencia al usuario, siempre puede encontrar el nombre de usuario de los reclamos y ejecutar una consulta en cualquier base de datos o servicio externo
Empecé a escribir mi propia política (a partir de ahora un simple requisito de rol) inyectando UserManager
en el constructor:
public class RoleHandler: AuthorizationHandler<RoleRequirement>
{
private UserManager<AppUser> UserManager;
public RoleHandler(UserManager<AppUser> usermanager)
{
UserManager = usermanager;
}
}
Ahora tengo un par de problemas:
INYECTAR UN SERVICIO CON ALCANCE EN UN SOLOTON
Se supone que las políticas duran toda la vida de la aplicación, por lo que sería un Singleton:
services.AddSingleton<IAuthorizationHandler, RoleHandler>();
pero el UserManager inyectado en el servidor de políticas es un servicio de alcance y eso no está permitido. La solución fue muy fácil, cambiando la configuración del servicio de políticas de un servicio único a un servicio con ámbito
services.AddScoped<IAuthorizationHandler, RoleHandler>();
pero no sé si eso causa algún problema o no.
ESCRIBIR UN MANEJADOR DE POLÍTICAS ASINCRÓNICO
Esta es mi implementación del HandleRequirementAsync
método:
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
AppUser user = UserManager.FindByIdAsync(context.User.Identity.Name).Result;
if (user!= null)
{
bool result = UserManager.IsInRoleAsync(user, requirement.Role.ToString()).Result;
if (result) context.Succeed(requirement);
}
return Task.CompletedTask;
}
Lo usé Task.Result
pero bloquea el hilo. No puedo usar await
porque eso haría que el método devolviera a en Task<Task>
lugar de a Task
y no puedo cambiarlo. ¿Como puedo resolver esto?
Solución del problema
no Task.CompletedTask
regreses
Cuando declara un método como async
, implícitamente devuelve un Task
cuando await
se golpea el primero:
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
AppUser user = await UserManager.FindByIdAsync(context.User.Identity.Name);
if (user!= null)
{
bool result = await UserManager.IsInRoleAsync(user, requirement.Role.ToString());
if (result) context.Succeed(requirement);
}
}
Task.CompletedTask
generalmente se usa cuando necesita implementar un Task
método de devolución de forma sincrónica, lo cual no es así.
No hay comentarios:
Publicar un comentario