asp.net MVC role based access to controller

2019-02-15 20:24发布

问题:

A lot of articles online on role based access speak of applying something like this to ensure role based access to a controller or action

[Authorize(Roles = "Admin, Manager")]
public class SomeController : Controller
{ 

}

All this is fine, but now if I need to implement my own custom role based access wherein I have roles in a [RoleMaster] table and the roles assigned to a user from a [User] table in another table called [UserRoles]. In my code I will have a user object in session which will now have a Roles list in it

public class RegisteredUsers
{

    //... other user properties

    public List<UserRole> Roles { get; set; }

}

public class UserRole
{

    public string RoleID { get; set; }
    public string RoleName { get; set; }
    //... other properties

}

Now how do I check for the UserRole.RoleName property in the Roles list in the RegisteredUsers object as matching against any of the values I have assigned to the Authorize attribute using : [Authorize(Roles = "Admin, Manager")]. In some case if the roles have either Admin or Manager they should get access. In some cases I will want them to have both Admin as well as Manager Role to get access.

Also, in the future if new roles get added to the system will I need to rebuild and redeploy my application with all the Authorize attributes redone?

I have not been able to find any clear example implementing the same, or perhaps I am not searching correctly. Please help me out in any way you can. Thanks for your time...

回答1:

You need to implement a custom IPrincipal (or a custom RoleProvider, but in my view IPrincipal is easier).

In your forms authentication controller, authenticate against your user table and create an IPrincipal with roles from your role table. You will probably also want to set a Forms Auth cookie while you're at it with your roles so you don't need to hit the database each request (or use a session). Have a look at the code in this question for an example of this approach.

If you don't have any custom attributes on your users, you may be able to use the built-in GenericIdentity and GenericPrincipal.

Edit - if you're storing your user information in the session, you'll just need to make sure you set HttpContext.Current.User to your session-derived IPrincipal at the start of each request (OnPostAuthenticate)

You will need to rebuild/redeploy to cater for new roles with this approach. If you want to dynamically assign roles and handle them at runtime, you'd need to implement a custom AuthorizationAttribute - this could take (e.g.) a string 'Operation' parameter which can be matched to roles in the DB. I would personally leave this until it becomes obvious you need it.



回答2:

Sounds like you might be outgrowing the role-based security design. If you need dynamic granular either/or privileges then you should start to at least look at a more claims-based approach.

You might be able to achieve some of what you are describing by implementing a custom IPrincipal like the above link shows (without full claims-based).

Hope this helps.