6

The authorize filter allows you to specified group of users that can access a controller or action:

[Authorize(Roles="Administrator")]
public class HomeController : Controller
{
    // code
}

I would like to know if it is possible to, instead, specify a group of users that cannot access a controller or action.

ajbeaven
  • 9,265
  • 13
  • 76
  • 121
  • 1
    I cannot imagine a scenario where switching from a white list implementation to a black list implementation would make sense. – Spencer Ruport Sep 04 '09 at 00:13
  • I don't want my Administrators to access the customer related controllers but I obviously need non-authorised users and Customers to be able to. – ajbeaven Sep 04 '09 at 00:27
  • There are many cases where it makes sense, and most authorization systems include support for denial. Consider a scenario where all users have permission to do something except for members of a specific role. – ShadowChaser Jul 01 '12 at 03:05

4 Answers4

5

I tried creating my own AuthorizationAttribute after twk's suggestion:

public class Restrict : AuthorizeAttribute
{
    private readonly string _role;

    public Restrict(string role)
    {
        _role = role;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        if (httpContext.User.IsInRole(_role))
            return false;

        return true;
    }
}

And I use it like this:

[Restrict("Administrator")]
public class HomeController : Controller
{
    // code
}

I'm unsure whether it is correct practice but it does the job.

ajbeaven
  • 9,265
  • 13
  • 76
  • 121
1

You should prepare your own ActionFilter which can implement such a feature. By default there is a rule of deny everything, but allow defined by Authorize action filter (as you already know).

Some inspiration can be found there

Community
  • 1
  • 1
twk
  • 3,122
  • 2
  • 26
  • 36
1

Based on ajbeaven's answer, I managed to extend it to list of Roles instead of one role.

Firstly the Restrict class:

public class Restrict : AuthorizeAttribute {
    private List<string> _roles;
    public string Roles {
        get {
            string roles = "";
            if (_roles != null && _roles.Count > 0) {
                int counter = 0;
                foreach (string role in _roles) {
                    counter++;
                    if (counter == _roles.Count) {
                        roles = role;
                    } else {
                        roles += role + ",";
                    }
                }
            }
            return roles;
        }
        set {
            _roles = new List<string>();
            string[] roles = value.Split(',');
            foreach (string role in roles) {
                _roles.Add(role);
            }
        }
    }

    public Restrict() {
        _roles = new List<string>();
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext) {
        bool result = true;
        if (httpContext == null) {
            throw new ArgumentNullException("httpContext");
        }
        foreach (string role in _roles) {
            if (httpContext.User.IsInRole(role)) {
                result = false;
                break;
            }
        }
        return result;
    }
}

Then add the AppRoles class to make the whole solution reusable:

public static class AppRoles {
    public const string Role1 = "Role1";
    public const string Role2 = "Role2";
}

Usage:

[Authorize]
[Restrict(Roles = AppRoles.Role1 + "," + AppRoles.Role2)]
    public ActionResult Index() {
    return View();
}
Community
  • 1
  • 1
Dzik
  • 55
  • 5
0

Simply restrict class:

public class Restrict : AuthorizeAttribute
    {
        public string RestrictedRoles;

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {          
            if (!String.IsNullOrEmpty(RestrictedRoles))
            {
                var roles = RestrictedRoles.Split(',').Select(r => r.Trim());
                foreach (var role in roles)
                {
                    if (httpContext.User.IsInRole(role))
                        return false;
                }
            }

            return true;
        }
    }

Usage

mikus
  • 3,042
  • 1
  • 30
  • 40