I am working on asp.net mvc 5. I want to assign permissions of controllers' action methods to roles dynamically without hard conding the roles in Authorize attribute.
Here is the scenario -
In my project, I have four roles - Student, Teacher, Program Officer and Admin.
I want that admin can change the accessability of each role whenever he wishes. I do not want to hard code the authorize attribute with role names before every action name of controller because admin will not then be able to change the permissions of each role.
I want to create a page where every action method of controller will be listed as checkbox and admin can select action checkboxes for a role. Then that role users will get accessability of those action methods.
Here I want to make the UI as following -
Can anyone please help me to do this by giving any suggestion or code or link?
Imagine you have service which returns array of roles based on controller and action name like this:
public class RoleProvider
{
public string[] Get(string controller, string action)
{
// get your roles based on the controller and the action name
// wherever you want such as db
// I hardcoded for the sake of simplicity
return new string[]{"Student", "Teacher"};
}
}
Now you can write your own authorization attribute something like this:
public class DynamicRoleAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var controller = httpContext.Request.RequestContext
.RouteData.GetRequiredString("controller");
var action = httpContext.Request.RequestContext
.RouteData.GetRequiredString("action");
// feed the roles here
Roles = string.Join("," ,_rolesProvider.Get(controller, action));
return base.AuthorizeCore(httpContext);
}
}
Now use your custom authorization attribute instead of older one like this:
[DynamicRoleAuthorize]
public ActionResult MyAction()
{
}
I think the only way is to implement your own Authorize Attribute where you can implement your own logic for authorization.
And in your case you should have a table where associate roles and controllers action and check this table in your custom Authorize Attribute.
While this does not give you the dynamics web page assignment you're looking for, If you are flexible in your approach... you can set up an Enum list of Roles Admin, Editor editor etc
, and pass them as a parameter object (ENUM) as a param, so that the DynamicRoleAuthorize
can use it load the roles that are allowed
from vivians blog The constructor accepts parameters of type object, that is the little trick. If you use parameters of type Enum, you will get the same error message as above. We can do that because an Enum is an object.
To ensure that we are passing parameters of type Enum, we check the type of every roles. If one role is not of type Enum, the constructor will throw an ArgumentException.
Then we set the standard Roles property with the name of our roles with the string.Join method.
using System;
using System.Linq;
using System.Web.Mvc;
namespace MvcApplication.HowTo.Attributes
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeEnumAttribute : AuthorizeAttribute
{
public AuthorizeEnumAttribute(params object[] roles)
{
if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))
throw new ArgumentException("roles");
this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
}
}
}