Se la nostra web application fa uso di ruoli, abbiamo tipicamente la necessità di mostrare un messaggio di "Accesso non autorizzato" nel caso in cui un utente cerchi di visitare una sezione del sito per cui non dispone dei necessari permessi.
Nel caso di ASP.NET MVC una possibile soluzione è quella di realizzare una action Unauthorized e di configurarla come loginUrl della forms authentication:
<authentication mode="Forms"> <forms loginUrl="~/Account/Unauthorized" timeout="2880" /> </authentication>
Supponiamo ora che un utente loggato provi a visitare un controller su cui non è autorizzato, ad esempio perché il suo uso è ristretto ai soli membri del gruppo Administrators:
[Authorize(Roles = "Administrators")] public class BackOfficeController : Controller { public ActionResult Index() { return this.View(); } }
In questo caso, la forms authentication farà scattare il redirect verso la action che abbiamo configurato che, a sua volta, restituirà una view contenente un opportuno messaggio di errore:
public ActionResult Unauthorized() { if (User.Identity.IsAuthenticated) { // Non sei autorizzato a visitare questa pagina... return this.View(); } var routeValues = this.RouteData.Values; foreach (var key in this.Request.QueryString.AllKeys) { routeValues.Add(key, this.Request.QueryString[key]); } return this.RedirectToAction("LogOn", routeValues); }
Questo comportamento permane solo nel caso in cui l'utente sia autenticato ossia, in altre parole, quando il redirect ha avuto luogo per una mancanza di permessi. Nel caso in cui l'utente sia anonimo, invece, deve essere ripristinato il funzionamento tradizionale, rimandando pertanto alla pagina di login: la seconda parte del metodo si occupa proprio di assolvere a questo compito, avendo cura di includere nell'URL tutti gli eventuali parametri (sia di querystring che di routing) con cui Unauthorized è stata invocata.
Un piccolo difetto di questo approccio è che, nel caso di utente non autenticato, vengono effettuati due redirect successivi, uno verso la action Unauthorized e il successivo su quella di LogOn. In realtà potrebbe essere più indicato un comportamento simile al Server.Transfer di ASP.NET Web Forms, ed evitare così un roundtrip addizionale verso il browser. Purtroppo questo metodo non è direttamente utilizzabile in ASP.NET MVC, ma comunque in rete si trovano diversi esempi di come implementare un TransferResult e migliorare, se necessario, anche questo aspetto.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Usare le collection expression per inizializzare una lista di oggetti in C#
Reactive form tipizzati con FormBuilder in Angular
Effettuare il binding di date in Blazor
Utilizzare gli snapshot con Azure File shares
Criptare la comunicazione con mTLS in Azure Container Apps
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Miglioramenti agli screen reader e al contrasto in Angular
Usare un KeyedService di default in ASP.NET Core 8
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Aggiungere interattività lato server in Blazor 8
Short-circuiting della Pipeline in ASP.NET Core