I'm having a huge problem in understanding Membership with MVC. We have in our project controllers named "Admin" and "SuperAdmin" and they are restricted to some users.
Do I have to use the Authorize Roles attribute on each Action or can I use a ActionFilter to check if an user can view a certain page?
And if I have to user Roles attribute, do I have to configure each user on the ASP.NET Configuration tool? For example, "SuperAdmin" will be only a few users (around 3 at top), making easy to use ASP.NET Configuration tool and tells it who these users are. But "Admin" users will be many more... how can I configure them?
I'm totally lost!
I need a great clarifying on that!
Thanks a lot!!!
You can apply the AuthorizeAttribute to controllers as well as actions. If you apply it to the controller, each method will have its access restricted with respect to the attribute. You can also apply another instance of the attribute to individual actions to further restrict access if necessary based on other roles. You will need to put the individual users in their roles for them to have access to role-controlled controllers/actions.
Related
We are developing a website and we have a controller that handles CRUD for a model e.g Country. Only the Administrator is allowed to perform CRUD operations. However we also want the controller to provide a JSON select list of entities to populate a drop-down. This pattern exists through out the application.
This means that we can't use the standard authorization attribute to restrict access to administrators at the entry to the controller. We need to decorate each action with specific authorize attribute.
Is the fact that we need multiple authorization levels on a single controller a bad sign? Does it suggest we are violating SRP?
What is the best pattern to deal with the fact many controllers relate to entities that need to be updatable only by Admin but provide a JSON select list for all authorized users?
Thanks
The only problem with doing this is the Risk that you might forget to protect an action that is supposed to be admin only.
Really the preferred way to approach this problem is to have an admin-only area on your site (using MVC areas).
http://msdn.microsoft.com/en-us/library/ee671793.aspx
http://sankarsan.wordpress.com/2012/04/14/asp-net-mvc-areasa-better-way-to-structure-the-application/
This way the entire www.site.com/admin section would be protected as admin-only.
I am a bit new to ASP.NET MVC and I have a bit of an ordeal. I am developing a website with several roles in it and of course the logic and gui that the user gets depends on the role (duh).
There are 10 separate roles in this application. They do share most of the same functionality but some screens will be different depending on which roles they are in.
Heres my question. All examples and tutorials I've read on the internet and the Apress book that I have been reading show an example how to implement roles with one role (Admin) in which the common way is to provide an Admin Controller (or even Admin area) for the authorized section of the site. However, what if there are 10 roles? Do I really need to code up 10 separate controllers?
Let me help the question by giving detail what is being developed. There will be a menu and the menu items will be filtered by role of what views(or pages) they can and cannot get.
The from what they select, it will provide them a restricted view(or authorized page) which from within will provide a plethora of functionality limited to just that role.
I know there are several different ways to do this, I just want to know what is the recommended or "clean" way.
Have any of you been in this situation and if so, how did you organize the logic for multiple roles? Separate all roles to separate controllers? Have few controllers but just apply authorize filtering on the action methods? Apply the role filtering within the views or partial views and leave the controllers alone?
Unfortunately there are little resources for how to implement several roles out there, I just want to know how to do it the "correct" way in terms of separating the logic.
I would put the pieces of functionality into partial views. Have one controller per piece of website and load partial views based on the role and what should be exposed.
I would only stray from that if you have an excessive amount of differences, like an administrator would possible have. Then I typically make an area to encapsulate that functionality.
Regardless of the controller separation I would definitely use partial views to minimize duplication of similar code. You will reap the benefits when you need to maintain that code.
Use Authorize on the action methods and apply the roles allowed for the operation.
Depending on what's appropriate for the scenario, build a list of available actions from the controller and send that to the view as part of the view model. In some cases its more appropriate to send a simpler view model that tells the view whether each operation is allowed i.e. CanDelete, CanEdit, CanViewDetailedInfo etc.
I'd start with that, and depending on the actual complexity re-factor to any combination of:
An ActionFilter that populates the available actions / instead of explicitly doing it in the controller
Use reflector to look for the list of roles applied in authorize / so you only specify roles once
Your own html helpers that take authorization into account. So when you declare an action link, its only output when the action is supported.
There are plenty of questions (and information) on setting up asp.net membership, role providers and the like. Whether or not you should use the built in platform provided by microsoft, or role extend the base classes and role your own.
I have decided to extend the default providers and implement my own membership and role providers. Now my question, is specifically around role authentication.
Traditionally, you would create roles maybe like 'Manager, Administrator, Employee, Super User' or whatever you have. But what would/should you do with respect to permissions which I consider to be a finer grain of control? Let me elaborate....
Within my asp.net mvc site I have different areas like administration, management, messaging, reporting etc. I would crate roles for each of these like 'Administrator', 'Manager', 'Reporter' etc. Without the appropriate role, you can't gain access to that area of the site. So I would lock down the entire controllers with this at the class level.
But now take one area as an example; messaging, and say I wanted to have finer grain permissions for CRUD; create a message, view/read messages, edit messages, delete messages etc.
Finally my question. How would it be best to implement this finer grain of control? One approach I see (not sure if it is a good one), is to just create asp.net membership roles for everything. So I might have....
Messenger (broad level role), CreateMessage, ReadMessage, EditMessage, DeleteMessage.
On one hand I would like some users to be able to read/view messages. But not necessarily create or delete them. Individual controller actions could have the specific roles applied.
Do you see any problems with this approach? Do you have a better idea?
Solution So Far
I have decided to create my own schema and implement custom membership and role providers. My schema includes;
User
UserProfile
Permission
PermissionAssignment
Role
RoleAssignment
Going to be away for the next day or two but will update with more information when I get a chance.
I think you should forget about roles on the authorization mechanism, ask for permissions instead (at the end a role is an agrupation of permissions), so if you look it that way, your Authorize Attribute should ask for an entity and action, not for a particular role. Something like:
[Authorize(Entities.Message, Actions.Create)]
public ActionResult CreateMessage()
[Authorize(Entities.Message, Actions.Edit)]
public ActionResult EditMessage()
[Authorize(Entities.Message, Actions.View)]
public ActionResult ViewMessage()
That way your roles do what they do best, abstract permissions collection instead of determining a inflexible way of access level.
EDIT: To handle specific rules like the one pointed by David Robbins, Manager A is not allowed to delete messages created by Manager B, assuming they both have the required permission to access this Controller Action, the Authorize is not responsible to check this type of rules, and even if you try to check that at Action Filter level it will be a pain, so what you can do is extend the Authorize validation to the ActionResult (injecting an action parameter holding the validation result), and let the ActionResult make the logic decision there with all the arguments in place.
This is a similar question, is not exactly the case pointed out here, but its a good starting point on extending the Authorize validation with Action Parameters.
With respect to your CRUD example, aren't you really talking about authorization, and would the authorization vary between the membership roles "Manager" and "Reporter"? I think you need to create a separate mechanism for those finer grained activities if the roles do not distinguish between a read and write authorization between messages.
If you were to create a role for each action - EditMessage, DeleteMessage - what will you do in the case when Manager A should NOT be able to delete messages for Manager B?
As well as adding [Authorize(Roles="Administrator")] etc above your controller. You can also put that attribute on the indiviual Actions too
I'm looking for an elegant pattern to solve this problem:
I have several user roles in my system, and for many of my controller actions, I need to deal with slightly different data.
For example, take
/Users/Edit/1
This allows a Moderator to edit a users email address, but Administrators to edit a user's email address and password.
I'd like a design for separating the two different bits of action code for the GET and the POST.
Solutions I've come up with so far are:
Switch inside each method, however this doesn't really help when i want different model arguments on the POST :(
Custom controller factory which chooses a UsersController_ForModerators and UsersController_ForAdmins instead of just UsersController from the controller name and current user role
Custom action invoker which choose the Edit_ForModerators method in a similar way to above
Have an IUsersController and register a different implementation of it in my IoC container as a named instance based on Role
Build an implementation of the controller at runtime using Castle DynamicProxy and manipulate the methods to those from role-based implementations
Im preferring the named IoC instance route atm as it means all my urls/routing will work seamlessly.
Ideas? Suggestions?
Woo, no answers. Here's my attempt at the IoC approach, I think I'll be going with this unless anyone has any other ideas.
Segregating Controller Logic Based on User Role in ASP.NET MVC
I have a super simple ASP.NET MVC application that uses RpxNow (OpenID) to allow users to login. I now want to let users edit their own account and provide administrator access to edit anyone's account.
I have two separate "Edit Account" views:
~/account/edit/
~/account/edit/1
The first loads the account details based on the logged in user. The second loads the account details using the supplied AccountId. The first would be for standard users, and the second for an administrator.
Firstly I need to define the roles (User, Admin) and then I need to assign a user account (or multiple) to that role.
Then I need to check the role in the controller. I like this concept:
http://schotime.net/blog/index.php/2009/02/17/custom-authorization-with-aspnet-mvc/
So, down to the questions:
Is there a simple way to define a list of roles in the web.config?
Is there a simple way to define which users are in which roles in the web.config?
Is there a way to do this WITHOUT using Membership / Role providers?
Am I approaching this from the wrong perspective? Should I be partioning the application into two branches and securing them based on folder authorisation?
I'm not a friend of storing authorization data in web.config. I prefer storing it in database or other xml files.
Have a look at Xml Membership / Role Provider. This uses Membership / Role for reading userdata but it shows a way storing and reading user authorization data from xml files.
Braching the application woulded move the issue and not solve.
Remember that the entire permissions plumbing still really revolves around IPrincipals, the Role/Membership providers are just window dressing to allow most applications to not have to write that plumbing code. In this case, you could easily add a database-backed (or just static if the list is short enough) list of roles and a list of users in roles and query that. Wrap it up behind a custom IPrincipal and stuff that puppy in there at the appropriate place and you are golden.