2010-12-16 11 views
31

Asp.net MVC2 redirige vers la page de connexion avec response 302 lorsque l'utilisateur authentifié n'a aucun droit.Attribut Asp.net MVC Authorize, rediriger vers la page "sans droits" personnalisée

Je voudrais diviser en deux actions

  1. Si l'utilisateur n'est pas authentifié alors faire ce qu'il fait, rediriger vers la page de connexion.
  2. Si l'utilisateur est authentifié mais n'a pas les droits requis, renvoyer le code d'état http approprié et ne montrer aucune page de droits.

Y at-il un moyen de le faire? Ou est-ce que je fais quelque chose de mal avec l'autorisation et l'authentification de formulaire? La seule façon dont je peux penser est en écrivant l'attribut authorize personnalisé, que je veux éviter.

+2

haha ​​"aucuns droits mec" page ... lol –

Répondre

9

Vous pouvez écrire un attribut d'autorisation personnalisé et dans la méthode AuthorizeCore si l'utilisateur n'est pas authentifié, renvoyer un HttpUnauthorizedResult et s'il est authentifié mais pas dans des rôles, effectuez une autre action que vous souhaitez. Notez que si vous renvoyez le code d'état 401, l'infrastructure FormsAuthentication finira par rediriger avec 302 vers la page de connexion.

+4

Mais ... vous ne pouvez renvoyer un bool de AuthorizeCore. Vous devez remplacer OnAuthorization pour retourner un ActionResult –

+1

@EduardoMolteni, vous pouvez remplacer la méthode 'HandleUnauthorizedRequest' afin de renvoyer le résultat souhaité. –

18

Vous pouvez écrire attribut filtre personnalisé comme celui-ci:

public class CustomAuthorizeAttribute : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (filterContext.HttpContext.User.Identity == null || !filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       filterContext.Result = new RedirectResult(System.Web.Security.FormsAuthentication.LoginUrl + "?returnUrl=" + 
       filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.RawUrl)); 
      } 

      //Check user right here 
      if (userNotRight) 
      { 
       filterContext.HttpContext.Response.StatusCode = 302; 
       filterContext.Result = new HttpUnauthorizedResult(); 
      } 
     } 
    } 

et de l'utiliser dans le contrôleur:

[CustomAuthorize] 
public class HomeController : Controller 
{ 

} 
+18

Vous devez utiliser AuthorizeAttribute au lieu de ActionFilterAttribute à des fins d'autorisation. – ReinierDG

+1

Oui, c'est vrai. – hellangle

+0

@ReinierDG donc, comment l'implémenter avec AuthorizeAttribute? – Bellash

7

Comme suggéré dans Customizing authorization in ASP.NET MVC, vous pouvez sous-classe la AuthorizeAttribute pour intercepter le mais- authentifié scénario non autorisé et remplacez le résultat par une redirection.

+0

C'est mieux, surtout pour autoriser les résultats en cache. –

6

Implémentez un AuthorizeAttribute personnalisé et ajoutez le remplacement suivant. Les bases sont de vérifier si l'utilisateur est authentifié mais pas autorisé, puis de rediriger vers votre propre page "Accès refusé". J'espère que cela t'aides!

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    base.OnAuthorization(filterContext); 

    // Check if user is authenticated and if this action requires authorization 
    if (filterContext.HttpContext.User.Identity.IsAuthenticated 
     && filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true) 
     || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true)) 
    { 
     List<object> attributes = new List<object>(filterContext.ActionDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true)); 
     attributes.AddRange(filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(AuthorizeAttribute), true)); 

     // Check all authorzation attributes 
     foreach (var attribute in attributes) 
     { 
      var authAttribute = attribute as AuthorizeAttribute; 
      if (authAttribute != null) 
      { 
       if (!filterContext.HttpContext.User.IsInRole(authAttribute.Roles)) 
       { 
        // User is not authorized so redirect to our access denied error page 
        filterContext.Result = new RedirectToRouteResult(
         new RouteValueDictionary 
          { 
           { "area", "" }, 
           { "controller", "Error" }, 
           { "action", "AccessDenied" } 
          }); 
        break; 
       } 
      } 
     } 
    } 
} 
3

similaires aux solutions proposées par @hellangle et @Andreas, j'ai utilisé le code suivant pour résoudre ce problème:

public class CustomizedAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var userAuthInfo = GetUserAuthInfo(); 

     if (!userAuthInfo.IsAuthenticated()) 
     { 
      filterContext.Result = new RedirectResult(UrlToYourLoginPage); 
      return; 
     } 

     if (!userAuthInfo.IsAuthorized()) 
     { 
      var result = new ViewResult {ViewName = "UnAuthorized"}; 
      result.ViewBag.Message = "Sorry! You are not authorized to do this!"; 
      filterContext.Result = result; 
     } 
    } 
} 

Bien sûr, vous devez implémenter la classe d'informations d'autorisation d'utilisateur et méthodes connexes (GetUserAuthInfo, IsAuthenticated, IsAuthorized) en fonction de vos besoins spécifiques. De plus, une vue nommée 'UnAuthorized' doit être placée dans un endroit que le moteur MVC peut trouver. Ensuite, il peut être utilisé sur une classe de contrôleur (indiqué dans la réponse de @ hellangle) ou une méthode d'action:

[CustomizedAuthorizeAttribute] 
public class TargetController : Controller 
{ 
    [CustomizedAuthorizeAttribute] 
    public ActionResult TargetAction() 
    { 
     // Your Code 
    } 

} 

Afin de fournir une stratégie différente de contrôle d'accès pour les différentes classes de contrôleur et méthodes d'action, met en œuvre un constructeur pour CustomizedAuthorizeAttribute classe qui accepte les paramètres représentant les informations de contrôle d'accès, puis instancie la classe CustomizedAuthorizeAttribute en conséquence.

Questions connexes