Dans ASP.NET MVC, vous pouvez baliser une méthode de contrôleur avec AuthorizeAttribute
, comme ceci:
[Authorize(Roles = "CanDeleteTags")]
public void Delete(string tagName)
{
// ...
}
Cela signifie que si l'utilisateur actuellement connecté n'est pas dans le rôle "CanDeleteTags", la méthode du contrôleur ne sera jamais appelée.
Malheureusement, en cas d'échec, AuthorizeAttribute
renvoie HttpUnauthorizedResult
, qui renvoie toujours le code d'état HTTP 401. Cela provoque une redirection vers la page de connexion.
Si l'utilisateur n'est pas connecté, cela est parfaitement logique. Cependant, si l'utilisateur est déjà connecté, mais n'a pas le rôle requis, il est difficile de le renvoyer à la page de connexion.
Il semble que cela AuthorizeAttribute
confond l'authentification et l'autorisation.
Cela semble être un peu une erreur dans ASP.NET MVC, ou est-ce que je manque quelque chose?
J'ai dû préparer un DemandRoleAttribute
qui sépare les deux. Lorsque l'utilisateur n'est pas authentifié, il renvoie HTTP 401, en l'envoyant à la page de connexion. Lorsque l'utilisateur est connecté, mais n'est pas dans le rôle requis, il crée un à la NotAuthorizedResult
place. Actuellement, cela redirige vers une page d'erreur.
Je n'avais sûrement pas à faire ça?
la source
Réponses:
Quand il a été développé pour la première fois, System.Web.Mvc.AuthorizeAttribute faisait la bonne chose - les révisions plus anciennes de la spécification HTTP utilisaient le code d'état 401 pour "non autorisé" et "non authentifié".
De la spécification d'origine:
En fait, vous pouvez voir la confusion ici - il utilise le mot «autorisation» quand il signifie «authentification». Dans la pratique quotidienne, cependant, il est plus logique de renvoyer un 403 Interdit lorsque l'utilisateur est authentifié mais non autorisé. Il est peu probable que l'utilisateur ait un deuxième ensemble d'informations d'identification qui lui donnerait accès - une mauvaise expérience utilisateur tout autour.
Tenez compte de la plupart des systèmes d'exploitation - lorsque vous essayez de lire un fichier auquel vous n'êtes pas autorisé à accéder, aucun écran de connexion ne s'affiche.
Heureusement, les spécifications HTTP ont été mises à jour (juin 2014) pour lever l'ambiguïté.
Extrait de "Hyper Text Transport Protocol (HTTP / 1.1): Authentication" (RFC 7235):
Extrait de "Hypertext Transfer Protocol (HTTP / 1.1): Semantics and Content" (RFC 7231):
Chose intéressante, au moment où ASP.NET MVC 1 a été publié, le comportement d'AutorizeAttribute était correct. Maintenant, le comportement est incorrect - la spécification HTTP / 1.1 a été corrigée.
Plutôt que d'essayer de modifier les redirections de la page de connexion d'ASP.NET, il est plus facile de résoudre le problème à la source. Vous pouvez créer un nouvel attribut avec le même nom (
AuthorizeAttribute
) dans l'espace de noms par défaut de votre site Web (c'est très important), puis le compilateur le récupérera automatiquement au lieu de celui standard de MVC. Bien sûr, vous pouvez toujours donner un nouveau nom à l'attribut si vous préférez adopter cette approche.la source
filterContext.HttpContext.User.Identity.IsAuthenticated
, vous pouvez simplement vérifierfilterContext.HttpContext.Request.IsAuthenticated
, ce qui est livré avec des contrôles nuls intégrés. Voir stackoverflow.com/questions/1379566/…Ajoutez ceci à votre fonction Login
Lorsque l'utilisateur y est redirigé mais est déjà connecté, il affiche la page non autorisée. S'ils ne sont pas connectés, il tombe et affiche la page de connexion.
la source
if (User.Identity != null && User.Identity.IsAuthenticated) return RedirectToRoute("Unauthorized");
où Non autorisé est un nom de route défini.J'ai toujours pensé que cela avait du sens. Si vous êtes connecté et que vous essayez d'accéder à une page qui nécessite un rôle que vous n'avez pas, vous êtes redirigé vers l'écran de connexion vous demandant de vous connecter avec un utilisateur qui a le rôle.
Vous pouvez ajouter une logique à la page de connexion qui vérifie si l'utilisateur est déjà authentifié. Vous pouvez ajouter un message amical qui explique pourquoi ils ont de nouveau été bousculés là-bas.
la source
Malheureusement, vous avez affaire au comportement par défaut de l'authentification par formulaires ASP.NET. Il existe une solution de contournement (je ne l'ai pas essayé) discutée ici:
http://www.codeproject.com/KB/aspnet/Custon401Page.aspx
(Ce n'est pas spécifique à MVC)
Je pense que dans la plupart des cas, la meilleure solution est de restreindre l'accès aux ressources non autorisées avant que l'utilisateur ne tente d'y arriver. En supprimant / grisant le lien ou le bouton qui pourrait les mener à cette page non autorisée.
Il serait probablement intéressant d'avoir un paramètre supplémentaire sur l'attribut pour spécifier où rediriger un utilisateur non autorisé. Mais en attendant, je considère l'AutorizeAttribute comme un filet de sécurité.
la source
Essayez ceci dans votre dans le gestionnaire Application_EndRequest de votre fichier Global.ascx
la source
Si vous utilisez aspnetcore 2.0, utilisez ceci:
la source
Dans mon cas, le problème était "La spécification HTTP a utilisé le code d'état 401 pour" non autorisé "et" non authentifié "". Comme l'a dit ShadowChaser.
Cette solution fonctionne pour moi:
la source