Attribut d'autorisation personnalisé ASP.NET MVC 4 avec codes d'autorisation (sans rôles)


121

Je dois contrôler l'accès aux vues en fonction des niveaux de privilège des utilisateurs (il n'y a pas de rôles, uniquement des niveaux de privilège pour les niveaux de fonctionnement CRUD attribués aux utilisateurs) dans mon application MVC 4.

Par exemple; sous AuthorizeUser sera mon attribut personnalisé et je dois l'utiliser comme ceci:

[AuthorizeUser(AccessLevels="Read Invoice, Update Invoice")]
public ActionResult UpdateInvoice(int invoiceId)
{
   // some code...
   return View();
}


[AuthorizeUser(AccessLevels="Create Invoice")]
public ActionResult CreateNewInvoice()
{
  // some code...
  return View();
}


[AuthorizeUser(AccessLevels="Delete Invoice")]
public ActionResult DeleteInvoice(int invoiceId)
{
  // some code...
  return View();
}

Est-il possible de le faire de cette façon?

Réponses:


243

Je pourrais le faire avec un attribut personnalisé comme suit.

[AuthorizeUser(AccessLevel = "Create")]
public ActionResult CreateNewInvoice()
{
    //...
    return View();
}

Classe d'attribut personnalisé comme suit.

public class AuthorizeUserAttribute : AuthorizeAttribute
{
    // Custom property
    public string AccessLevel { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (!isAuthorized)
        {                
            return false;
        }

        string privilegeLevels = string.Join("", GetUserRights(httpContext.User.Identity.Name.ToString())); // Call another method to get rights of the user from DB

        return privilegeLevels.Contains(this.AccessLevel);           
    }
}

Vous pouvez rediriger un utilisateur non autorisé dans votre personnalisation AuthorisationAttributeen remplaçant la HandleUnauthorizedRequestméthode:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary(
                    new
                        { 
                            controller = "Error", 
                            action = "Unauthorised" 
                        })
                );
}

J'ai essayé votre exemple de HandleUnauthorizedRequest mais lorsque je spécifie le RouteValueDictionary, il me redirige simplement une route qui n'existe pas. Il ajoute la route vers laquelle je veux rediriger l'utilisateur vers la route à laquelle l'utilisateur voulait accéder ... si j'obtiens quelque chose comme: localhost: 9999 / admin / Home quand je voulais localhost: 9999 / Home
Marin

1
@Marin Essayez d'ajouter area = string.Empty dans le RouteValueDictionary
Alex

30
J'étais en train de voter mais j'ai vu "if (condition) {return true;} else {return false;}" à la fin ....
GabrielBB

1
@Emil Je retournerais simplement le booléen que la méthode String.Contains m'a donné. Mais ce n'est pas pertinent, je n'ai pas voté contre, je n'ai tout simplement pas voté pour hehe.
GabrielBB

2
.Name.ToString()est redondant, car la Namepropriété est déjà une chaîne
FindOutIslamNow

13

Voici une modification pour le précédent. répondre. La principale différence est que lorsque l'utilisateur n'est pas authentifié, il utilise la méthode originale "HandleUnauthorizedRequest" pour rediriger vers la page de connexion:

   protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {

        if (filterContext.HttpContext.User.Identity.IsAuthenticated) {

            filterContext.Result = new RedirectToRouteResult(
                        new RouteValueDictionary(
                            new
                            {
                                controller = "Account",
                                action = "Unauthorised"
                            })
                        );
        }
        else
        {
             base.HandleUnauthorizedRequest(filterContext);
        }
    }

3

Peut-être que cela est utile à n'importe qui à l'avenir, j'ai implémenté un attribut d'autorisation personnalisé comme celui-ci:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class ClaimAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly string _claim;

    public ClaimAuthorizeAttribute(string Claim)
    {
        _claim = Claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;
        if(user.Identity.IsAuthenticated && user.HasClaim(ClaimTypes.Name, _claim))
        {
            return;
        }

        context.Result = new ForbidResult();
    }
}

0

Si vous utilisez l'API WEB avec des revendications, vous pouvez utiliser ceci:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AutorizeCompanyAttribute:  AuthorizationFilterAttribute
{
    public string Company { get; set; }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var claims = ((ClaimsIdentity)Thread.CurrentPrincipal.Identity);
        var claim = claims.Claims.Where(x => x.Type == "Company").FirstOrDefault();

        string privilegeLevels = string.Join("", claim.Value);        

        if (privilegeLevels.Contains(this.Company)==false)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Usuario de Empresa No Autorizado");
        }
    }
}
[HttpGet]
[AutorizeCompany(Company = "MyCompany")]
[Authorize(Roles ="SuperAdmin")]
public IEnumerable MyAction()
{....
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.