将控制器操作权限动态分配给 asp.net MVC 中的角色

Posted

技术标签:

【中文标题】将控制器操作权限动态分配给 asp.net MVC 中的角色【英文标题】:Dynamically assign controller action permissions to roles in asp.net MVC 【发布时间】:2017-03-11 04:06:45 【问题描述】:

我正在研究 asp.net mvc 5。我想动态地将控制器的操作方法的权限分配给角色,而不是硬约束 Authorize 属性中的角色。

这是场景 - 在我的项目中,我有四个角色——学生、教师、项目官员和管理员。 我希望管理员可以随时更改每个角色的可访问性。我不想在控制器的每个操作名称之前使用角色名称对授权属性进行硬编码,因为管理员将无法更改每个角色的权限。

我想创建一个页面,其中控制器的每个操作方法都将被列为复选框,管理员可以为角色选择操作复选框。然后该角色用户将获得这些操作方法的可访问性。

这里我想让 UI 如下 -

任何人都可以通过提供任何建议或代码或链接来帮助我做到这一点吗?

【问题讨论】:

您是否已经在项目中使用角色? 这里我从 AspNetRole 表中检索了角色。我为这张表设置了四个角色。但我担心的是如何允许管理员从 UI 中将操作方法​​的权限分配给角色。此 UI 用于演示目的。我想这样创作。 我还没有为控制器方法分配角色。 嗨,我也在寻找这个解决方案,也可以映射到菜单 【参考方案1】:

我认为唯一的方法是实现自己的授权属性,您可以在其中实现自己的授权逻辑。

在您的情况下,您应该有一个关联角色和控制器操作的表,并在您的自定义授权属性中检查此表。

【讨论】:

【参考方案2】:

假设你有一个服务,它根据控制器和操作名称返回角色数组,如下所示:

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";
    

现在您可以编写自己的授权属性,如下所示:

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);
    

现在使用您的自定义授权属性,而不是像这样的旧属性:

[DynamicRoleAuthorize]
public ActionResult MyAction()



【讨论】:

您好,您能否编辑或修改此如何以性能方式从 Db 或配置文件中获取角色,以便我们可以Roles = string.Join("," ,_rolesProvider.Get(controller, action)); 这将是一个很大的帮助。因为,当我在代码中尝试这个时,它会在编译过程中报错! 角色映射在哪里处理,即在哪里配置、检索和检查?另外,这可以处理运行时,还是需要重新启动应用程序?在您的解决方案中,请说明我感兴趣 @transformer roleProvider 是一个虚构的类,负责根据控制器和动作获取相关角色。你可以自己写。想象一下,您在数据库中有一个表,您为每个控制器和操作分配角色,然后通过此类获取分配的角色。每次调用操作时都会处理角色映射,因此如果您分配了新角色,则无需重新启动应用程序。 @SamFarajpourGhamari 如果路线有区域而没有区域怎么办??【参考方案3】:

虽然这不会为您提供您正在寻找的动态网页分配,但如果您的方法很灵活...您可以设置一个Enum list of Roles Admin, Editor editor etc,并将它们作为参数对象 (ENUM) 传递为一个参数,以便DynamicRoleAuthorize 可以使用它加载允许的角色

来自vivians blog 构造函数接受对象类型的参数,这是一个小技巧。如果您使用 Enum 类型的参数,您将收到与上述相同的错误消息。我们可以这样做,因为 Enum 是一个对象。 为了确保我们传递 Enum 类型的参数,我们检查每个角色的类型。如果一个角色不是 Enum 类型,则构造函数将抛出 ArgumentException。 然后我们使用 string.Join 方法将标准 Roles 属性设置为我们的角色名称。

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)));
    
   

【讨论】:

以上是关于将控制器操作权限动态分配给 asp.net MVC 中的角色的主要内容,如果未能解决你的问题,请参考以下文章

带有权限代码的 ASP.NET MVC 4 自定义授权属性(无角色)

ASP.NET MVC3 角色和权限管理 -> 使用运行时权限分配

ASP .NET MVC Redirecttoaction 将参数传递给 Index 但值为空

ASP.NET MVC 中的动态路由操作名称

将复选框的值传递给 asp.net mvc4 中的控制器操作

C#获取类以及类下的方法(用于Asp.Net MVC)