Need some insight into how to manage roles in my application (ASP.NET MVC3)

I am developing some kind of website, which is a kind of workplace on the Internet, there will be some users and some current computer programming projects, and each user can have several roles, for example, one specific user can be a project manager for a project and a developer for another project. Naturally, the project manager has more authority than the developer in the project. my question is how to manage this in my code neatly? I was going to use my own role provider and use the Authorize attribute with this, but this is not enough, since I need a project identifier plus a user identifier to find the user role in a specific project.

+6
source share
7 answers

First, you will need to create additional tables for advanced role management, such as projects , as well as a relationship with users in the context of operations , which could be your controller actions .

One way to do this is to create your own table for roles . In this case, you will only use Asp net membership users , but it all depends on your requirements.

Secondly, you need to process it in MVC . In my opinion, the best way is to implement it using your own custom attribute Authorization and decorate your actions with your authorization attribute instead of the [Authorization] attribute.

It is very simple.

 [CustomAuthorize] //[Authorize] public ActionResult GetProjectTasks(string projectname) { } 

To do this, you need to assign your class from FilterAttribute , as well as implement the IAuthorizationFilter interface.

  public void OnAuthorization(AuthorizationContext filterContext) { HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie != null) { FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); var identity = new GenericIdentity(authTicket.Name, "Forms"); var principal = new GenericPrincipal(identity, new string[] { authTicket.UserData }); filterContext.HttpContext.User = principal; } var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; var action = filterContext.ActionDescriptor.ActionName; var user = filterContext.HttpContext.User; var ip = filterContext.HttpContext.Request.UserHostAddress; var isAccessAllowed = CustomAuthenticationLogic.IsAccessAllowed(controller, action, user, ip); if (!isAccessAllowed) { // Code if user is authenticated FormsAuthentication.RedirectToLoginPage(); } } 

In the OnAuthorization method OnAuthorization you can get all the information that may be required in your custom authorization logic, for example, HttpContext , Controller name, Action name. You can simply call your authentication logic from this method. Your custom authentication logic might look like this.

  public class CustomAuthenticationLogic { public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip) { // // Your custom logic here // } } 
+6
source

I recently did some research and can assure you:

  • ASP.NET built-in functions will most likely not help (there is no way to take into account things like project identifier)
  • The role-based access model is most suitable; there are various ways to implement it. The AzMan proposed by Rusted is actually good, but managing rules related to the context can be difficult. For example: User A performs operation B in project C, while he can be said on Sunday. Take a look at the azman.
  • Mixing access rules with code is very bad. Your security model should not be related to how the application (ASP.NET MVC) works, so this is wrong:
 var isAllowed = AccessControl.IsAccessAllowed(controller, action, user, ip); 

it should look like this:

 var isAllowed = AccessControl.IsAccessAllowed(user, operation, context); 

then you can use it whenever you want in every action or wrap it as an attribute.

where is the operation "Login", "Reply to a message", "Reading topics", etc., the context is another, like you are "project id", "day of the week", "user ip", etc.

many things can be written, for example, role overlap, context, etc. In short: Google for the "role-based access model on the .NET platform" may probably be easier to write a small custom security infrastructure. Ensure it works with users, roles, operations, and the project ID

Operations are assigned to roles, Roles are assigned to users with a specific project identifier, you can rigidly define operations and roles, so there will be only one small change in your database: mapping a user to roles

+4
source

If you have more complex rules and attributes are not enough, you can calculate in your controller if the user can access some functions and add properties to the ViewModel that reflect access or lack of access to these functions.

Thus, your presentation will be very subtle, it will display material depending on these ViewModel buffering properties.

So, imagining that your user can only read, you can have the bool IsReadOnly property, which will be filled by the controller, depending on the authorization rules, and this will be used in the view, for example, to generate shortcuts instead of Textboxes.

+2
source

I like the basic idea with AzMan - it's a concept of programming against operations.

Operations are very detailed things that should not be duplicated in use and are determined only by the developer. By combining operations with tasks and tasks in roles, and then defining the principles of roles (users and groups) for roles, you have a strong model for determining authorization in your application. Since you program directly for operations, your code does not need to know what roles the user has and which can be changed by the administrator at run time. In fact, someone can define a completely different set of roles to use the operations you use in your code, and you wonโ€™t need to change the code at all. Where the real power lies.

I do not mean "use AzMan in your application" (but maybe you should try). This is a powerful model, but it is also complex and probably too complex for simple things. If you have only one or two roles, and the actions that they protect do not overlap or may not change, then it is probably not justified.

+2
source

I suggest you create your own Authorize filter by expanding the built-in AuthorizeAttribute filter instead of implementing the IAuthorizationFilter interface. The built-in AuthorizeAttribute does a lot of plumbing work that takes care of the problem with the cache and other materials, and if you are going to implement an interface, you must do all of this.

You must override the AuthorizeCore method, and there you have all your role verification logic. user id you need to save in the session and project id , you need to find out.

 public override bool AuthorizeCore(HttpContextBase httpContext) { } 

The source code for AuthorizeAttribute is http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/913d37658a44#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs

Custom startup attribute: http://msdn.microsoft.com/en-us/library/ee707357(v=vs.91).aspx

+2
source

You may have groups based on roles .

Then add other users to specific groups. Groups can be>

 1) Admin Group 2) Developer Group 3) Project1-QA Group 4) Project2-Manager Group 

Save the display of [user - group] and [group - projects] , depending on the design of your database.

You can have as many roles (groups) for one user as you want.

+2
source

A very simple approach - to control access at the whole site level, you can add an INT column to the user table and map each bit of this INT to [flags] Enum, for example. [Flags] enum Access { UpdateProjects, AddProjects } .

To control access to each project, create a table with a name, for example. ProjectAccessControl with three columns: ProjectID (foreign key to the Project table), UserID (foreign key to the user table) and Role (INT). The Role column is an INT, and each bit of it should mean a different logical flag (as in the previous example, you can match this with an enumeration in C #) and say that if the first bit is on, then the user has permission to update the description, if the second bit is on, the user can change schedules, etc.

 [Flags] enum ProjectAccessRole { UpdateDescription, ChangeSchedule, etc... } 

In the code, you can check whether the user role has the right to update the schedule in this way:

 if( (intUserRole & ProjectAccessRole.ChangeSchedule) == ProjectAccessRole.ChangeSchedule) { /*user has right*/ } 

Then you can transfer this check to a simple function that takes two parameters: 1) a role that should be checked if it has 2) a role. Then you just call HasRights(intUserRole, ProjectAccessRole.ChangeSchedule); .

+1
source

Source: https://habr.com/ru/post/915034/


All Articles