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

发布于 2024-12-02 19:57:19 字数 943 浏览 2 评论 0 原文

ASP.NET MVC 允许用户在设计时为功能(即操作)分配权限,如下所示。

[Authorize(Roles = "Administrator,ContentEditor")]
public ActionResult Foo()
{
    return View();
}

要实际检查权限,可以在 (Razor) 视图中使用以下语句:

@if (User.IsInRole("ContentEditor"))
{
    <div>This will be visible only to users in the ContentEditor role.</div>
}

这种方法的问题是所有权限必须在设计时设置并分配为属性 /em>。 (以允许附加权限)的机制,例如 [Authorize(Roles = "Administrator,ContentEditor")]。

(属性是与 DLL 一起编译的,因此我目前不知道在运行时应用属性 在我们的用例中,客户端需要能够在部署后更改哪些用户拥有哪些权限,

例如,客户端可能希望允许具有 ContentEditor 角色的用户执行以下操作:编辑特定内容的某些内容可能不允许用户编辑查找表值,但现在客户端希望允许此操作而不授予用户所有下一个更高角色的权限,相反,客户端只想。 em>修改用户当前角色可用的权限

可以使用哪些策略来允许在外部定义 MVC 控制器/视图/操作的权限。属性(如在数据库中)并评估和应用

如果可能的话,我们非常希望尽可能地坚持 ASP.NET 成员资格和角色提供程序功能,以便我们可以继续利用它提供的其他好处。

预先感谢您的任何想法或见解。

ASP.NET MVC allows users the ability to assign permissions to functionality (i.e. Actions) at Design Time like so.

[Authorize(Roles = "Administrator,ContentEditor")]
public ActionResult Foo()
{
    return View();
}

To actually check the permission, one might use the following statement in a (Razor) view:

@if (User.IsInRole("ContentEditor"))
{
    <div>This will be visible only to users in the ContentEditor role.</div>
}

The problem with this approach is that all permissions must be set up and assigned as attributes at design time. (Attributes are compiled in with the DLL so I am presently aware of no mechanism to apply attributes (to allow additional permissions) such as [Authorize(Roles = "Administrator,ContentEditor")] at runtime.

In our use case, the client needs to be able to change what users have what permissions after deployment.

For example, the client may wish to allow a user in the ContentEditor role to edit some content of a particular type. Perhaps a user was not allowed to edit lookup table values, but now the client wants to allow this without granting the user all the permissions in the next higher role. Instead, the client simply wants to modify the permissions available to the user's current role.

What options are strategies are available to allow permissions on MVC Controllers/Views/Actions to be defined outside of attributes (as in a database) and evaluated and applied at runtime?

If possible, we would very much like to stick as closely as we can to the ASP.NET Membership and Role Provider functionality so that we can continue to leverage the other benefits it provides.

Thank you in advance for any ideas or insights.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一瞬间的火花 2024-12-09 19:57:19

可使用哪些策略来允许 MVC 上的权限
在属性之外定义的控制器/视图/操作(如在
数据库)并在运行时评估和应用?

自定义 Authorize 属性是实现此目的的一种可能性:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        Roles = ... go ahead and fetch those roles dynamically from wherever they are stored
        return base.AuthorizeCore(httpContext);
    }
}

然后:

[MyAuthorize]
public ActionResult Foo()
{
    return View();
}

What options are strategies are available to allow permissions on MVC
Controllers/Views/Actions to be defined outside of attributes (as in a
database) and evaluated and applied at runtime?

A custom Authorize attribute is one possibility to achieve this:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        Roles = ... go ahead and fetch those roles dynamically from wherever they are stored
        return base.AuthorizeCore(httpContext);
    }
}

and then:

[MyAuthorize]
public ActionResult Foo()
{
    return View();
}
剑心龙吟 2024-12-09 19:57:19

由于我很懒,所以我懒得滚动自己的属性,并为此使用 FluentSecurity 。除了能够在运行时应用规则之外,它还允许以自定义方式检查角色成员资格。就我而言,我为每个角色都有一个配置文件设置,然后我实现如下所示的内容;

// Map application roles to configuration settings
private static readonly Dictionary<ApplicationRole, string> 
    RoleToConfigurationMapper = new Dictionary<ApplicationRole, string>
        {
            { ApplicationRole.ExceptionLogViewer, "ExceptionLogViewerGroups" }
        };

然后像这样应用应用程序角色

SecurityConfigurator.Configure(
    configuration =>
    {
        configuration.GetAuthenticationStatusFrom(() =>
            HttpContext.Current.User.Identity.IsAuthenticated);
        configuration.GetRolesFrom(() => 
            GetApplicationRolesForPrincipal(HttpContext.Current.User));
        configuration.ForAllControllers().DenyAnonymousAccess();
        configuration.For<Areas.Administration.Controllers.LogViewerController>()
            .RequireRole(ApplicationRole.ExceptionLogViewer);
    });

filters.Add(new HandleSecurityAttribute());

,然后由您执行检查

public static object[] GetApplicationRolesForPrincipal(IPrincipal principal)
{
    if (principal == null)
    {
        return new object[0];
    }

    List<object> roles = new List<object>();
    foreach (KeyValuePair<ApplicationRole, string> configurationMap in
             RoleToConfigurationMapper)
    {
        string mappedRoles = (string)Properties.Settings.Default[configurationMap.Value];

        if (string.IsNullOrEmpty(mappedRoles))
        {
            continue;
        }

        string[] individualRoles = mappedRoles.Split(',');
        foreach (string indvidualRole in individualRoles)
        {
            if (!roles.Contains(configurationMap.Key) && principal.IsInRole(indvidualRole))
            {
                roles.Add(configurationMap.Key);
                if (!roles.Contains(ApplicationRole.AnyAdministrationFunction))
                {
                    roles.Add(ApplicationRole.AnyAdministrationFunction);
                }
            }
        }
    }

    return roles.ToArray();
}

。您当然可以从数据库中提取角色。这样做的好处是我可以在开发过程中应用不同的规则,而且有人已经为我完成了艰苦的工作!

As I'm lazy I couldn't be bothered rolling my own attribute and used FluentSecurity for this. In addition to the ability to apply rules at run time it allows a custom way to check role membership. In my case I have a configuration file setting for each role, and then I implement something like the following;

// Map application roles to configuration settings
private static readonly Dictionary<ApplicationRole, string> 
    RoleToConfigurationMapper = new Dictionary<ApplicationRole, string>
        {
            { ApplicationRole.ExceptionLogViewer, "ExceptionLogViewerGroups" }
        };

the application roles are then applied like so

SecurityConfigurator.Configure(
    configuration =>
    {
        configuration.GetAuthenticationStatusFrom(() =>
            HttpContext.Current.User.Identity.IsAuthenticated);
        configuration.GetRolesFrom(() => 
            GetApplicationRolesForPrincipal(HttpContext.Current.User));
        configuration.ForAllControllers().DenyAnonymousAccess();
        configuration.For<Areas.Administration.Controllers.LogViewerController>()
            .RequireRole(ApplicationRole.ExceptionLogViewer);
    });

filters.Add(new HandleSecurityAttribute());

and then the check is performed by

public static object[] GetApplicationRolesForPrincipal(IPrincipal principal)
{
    if (principal == null)
    {
        return new object[0];
    }

    List<object> roles = new List<object>();
    foreach (KeyValuePair<ApplicationRole, string> configurationMap in
             RoleToConfigurationMapper)
    {
        string mappedRoles = (string)Properties.Settings.Default[configurationMap.Value];

        if (string.IsNullOrEmpty(mappedRoles))
        {
            continue;
        }

        string[] individualRoles = mappedRoles.Split(',');
        foreach (string indvidualRole in individualRoles)
        {
            if (!roles.Contains(configurationMap.Key) && principal.IsInRole(indvidualRole))
            {
                roles.Add(configurationMap.Key);
                if (!roles.Contains(ApplicationRole.AnyAdministrationFunction))
                {
                    roles.Add(ApplicationRole.AnyAdministrationFunction);
                }
            }
        }
    }

    return roles.ToArray();
}

You could of course pull roles from a database. The nice thing about this is that I can apply different rules during development, plus someone has already done the hard work for me!

樱娆 2024-12-09 19:57:19

您还可以考虑执行基于任务/活动的安全性,并动态地将执行这些任务的权限分配给不同的组

http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/

您需要稍微修改提供程序以处理此问题,但可以与 .net 授权保持一致

http://www.lhotka.net/weblog/PermissionbasedAuthorizationVsRolebasedAuthorization.aspx

You could also consider doing task/activity based security and dynamically assign permission to perform those tasks to different groups

http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/

You would need to mangle the provider a little bit to work with this but it is possible to stay inline with the .net authorisation

http://www.lhotka.net/weblog/PermissionbasedAuthorizationVsRolebasedAuthorization.aspx

亢潮 2024-12-09 19:57:19

如果您需要进行基于方法或控制器的授权(拒绝访问整个方法或控制器),那么您可以覆盖控制器库中的 OnAuthorization 并进行您自己的授权。然后,您可以构建一个表来查找分配给该控制器/方法的权限并从那里开始。

您还可以进行自定义全局过滤器,这非常相似。

使用第二种方法的另一种选择是这样说:

@if (User.IsInRole(Model.MethodRoles)) 
{ 
    <div>This will be visible only to users in the ContentEditor role.</div> 
} 

然后在控制器中使用分配给该方法的角色填充 MethodRoles。

If you need to do Method or Controller based authorization (deny access to the whole method or controller) then you can override OnAuthorization in the controller base and do your ouwn authorization. You can then build a table to lookup what permissions are assigned to that controller/method and go from there.

You can also do a custom global filter, which is very similar.

Another option, using your second approach, is to say something like this:

@if (User.IsInRole(Model.MethodRoles)) 
{ 
    <div>This will be visible only to users in the ContentEditor role.</div> 
} 

And then in your controller populate MethodRoles with the roles assigned to that method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文