Tutorial ed esempi/Authorization Helper
Authorization Helper
Autorizzazioni personalizzate in ASP.NET
Con riferimento a "Provider di criteri di autorizzazione personalizzati"
Vogliamo ottenere un risulatato di questo tipo: una policy custom che autorizzerà l'utente all'accesso solo se l'utente appartiene a una unit specificata in un file di configurazione.
// Controller
[Authorize(Policy = "UserCanNavigate")]
public IActionResult Index()
{
return View();
}
Questo decoratore dichiara che l'azione Index è accessibile solo da utenti che rispettino le condizioni della nostra policy UserCanNavigate.
Questa tipologia di decoratore in .net può essere applicata a più livelli: intere aree, singoli controller, singole azioni o pagine razor.
Ulteriori informazioni possono essere recuperate a https://learn.microsoft.com/en-us/aspnet/core/security/authorization/simple
Per costruire ciò, iniziamo a costruire una classe che contenga il Requirement. Questo sarà, in questo caso, estremamente semplice, ma in casi più articolati conterrà i parametri forniti al decoratore.
// Requirement class. Does not need to be strictly internal
internal class UserCanNavigateRequirement : IAuthorizationRequirement
{ }
A questo punto costruiamo anche l'handler della policy, il quale conterrà la business logic del nostro decoratore.
// Auth handler. This will check if a user is in a unit whose id is in a configuration file
internal class UserCanNavigateHandler : AuthorizationHandler
{
private readonly IUserRepo _userRepo;
private readonly AuthorizationSettings _authorizationSettings;
protected UserSessionData UserSessionData { get; set; } // Il costruttore inietta il servizio user, i dati di sessione dello user che fa la richiesta e i dati di configurazione inerenti all'autorizzazione. Da quest'ultimo recupereremo l'id della unit.
public UserCanNavigateHandler(IUserRepo userRepo,
ISessionHelper sessionHelper,
IHttpContextAccessor accessor,
IOptions authorizationSettings)
{
_userRepo = userRepo;
_authorizationSettings = authorizationSettings.Value;
UserSessionData = sessionHelper.GetDatiUtente(accessor.HttpContext);
} protected async override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserCanNavigateRequirement requirement)
{
// Se non troviamo uno user nella session, probabilmente non siamo loggati. In ogni caso, la nostra policy respinge la richiesta.
if(UserSessionData == null)
{
context.Fail();
}
else
{
// Recuperiamo tutte le unit di cui l'utente fa parte
var units = await _userRepo.GetUnitsByUser(UserSessionData.UserToken);
if (units.Select(u => u.Id).Contains(_authorizationSettings.BasicNavigatorUserUnitId))
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
}
//return Task.CompletedTask;
}
}
Concludiamo registrando la policy. Per fare questo, all'aggiunta del servizio di autorizzazione indichiamo la nostra nuova policy
// Startup or service building
services.AddAuthorization(options =>
{
options.AddPolicy("UserCanNavigate", policy =>
policy.Requirements.Add(new UserCanNavigateRequirement()));
});