Dynamically assign controller action permissions to roles in asp.net MVC

岁酱吖の 提交于 2019-12-03 03:41:49

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)));
    }
   }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!