ASP.NET MVC 3 Custom Authorisation [closed]

2019-01-17 13:31发布

问题:

I am writing an ASP.NET MVC 3 application and I have a number of roles:

System Admin, Customer Admin, Budget Owner, App Owner

I know that I can easily restrict access to certain controllers (and action methods) using the [Authorize(Roles="...")] attribute.

However some of the authorisation is not based purely on role, but on permissions. For example the budget owners should only be able to access budgets assigned to their cost centre - not other peoples budgets.

At present I have some code within the action methods to check for this:

if(UserCapabilities.CanAccessBudget(budgetId))
{
  // get budget and show view
}
else
{
  // redirect to index action
}

This is starting to make my code messy and make checking security a nightmare - as I have many action methods that need these different types of authorisation checks.

An idea that I have had is to write some custom attributes that I can use to decorate my action methods and clean up my code:

//
// GET: /Budgets/View/1
[CanAccessBudget]
public ActionResult View(int id)
{
 //...
}

What do people think? Is writing custom attributes the cleanest and most maintainable way to go?

回答1:

You could write a custom authorization attribute:

public class CanAccessBudgetAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (isAuthorized)
        {
            var request = httpContext.Request;
            var budgetId = request.RequestContext.RouteData.Values["budgetId"] 
                ?? request["budgetId"];
            var currentUser = httpContext.User.Identity.Name;
            return HasPermissionsForBudget(currentUser, budgetId);
        }
        return isAuthorized;
    }
}

and then:

[CanAccessBudget]
public ActionResult View(int id)
{
    //...
}


回答2:

It would be better to put the authorize/redirect logic into an ActionFilterAttribute, because you are looking for permissions (which are based upon action parameters, not purely on which roles the user occupies).

Although refactoring logic into an attribute that only gets used once can get messy (with a ton of attributes).