在 ASP.NET 网站中,是否应该为管理员分配多个角色?

In an ASP.NET website, should Administrators be assigned multiple roles?

这个问题确实适用于可以为单个用户分配多个角色的任何网站或企业系统。

在 ASP.NET 身份中,您有 IdentityUserIdentityRole,其中用户可以有 0 个或多个角色。然后控制器操作由 [Authorize(Roles = "roleName")]

保护

给定一个具有以下 3 个简单角色的简单概念系统:

Administrator
Manager
User

...应该有权访问所有控制器操作的简单管理员类型用户:

JoeAdmin

以及以下示例 Web API 控制器:

public IHttpActionResult GetForUsersAndAbove()
{
    //
}

public IHttpActionResult GetForAdminsOnly()
{
    //
}

系统应该这样设计:

  1. 只为 JoeAdmin 分配一个角色——管理员,或者
  2. JoeAdmin 被分配给 Administrator、Manager 和 User?

我提出这个问题的动机是在授权控制器操作时。如果仅向 JoeAdmin 分配了管理员角色,则根据以下授权属性,他将无法访问 GetForUsersAndAbove(),因为他不是用户角色的成员

[Authorize(Roles = "User")]
public IHttpActionResult GetForUsersAndAbove()
...

[Authorize(Roles = "Administrator")]
public IHttpActionResult GetForAdminsOnly()
...

那么问题来了,GetForUsersAndAbove()应该用

修饰吗
[Authorize(Roles = "User, Manager, Administrator")]

让他可以访问?

系统是否应该基本上为 JoeAdmin 分配 所有角色,以便他可以访问所有控制器方法,即使它们被标记为 [Authorize(Roles = "User")]

编辑

如果我对控制器操作使用以下约定

[Authorize(Roles = "User")]
public IHttpActionResult GetForUsers()

并且预计如果 JoeAdmin 应该访问此方法,他也应该是 User 角色的成员,这会导致 UI 在一个假想的用户管理屏幕上出现问题:

这是一个场景:您是系统的新用户,负责管理用户。您添加了一个新用户 JaneAdmin,目的是让她可以 full/unrestricted 访问系统。您会看到 3 个复选框:AdministratorManagerUser。如果没有文档来指导您,您会勾选哪个复选框?如果我设身处地为那个用户着想,我会直觉地勾选 "Administrator",期望它会提供完全访问权限。我还可以想象当 JaneAdmin 发现她被锁定在简单的用户级操作之外时的沮丧。所以 UI 要求所有 3 个复选框都应该被勾选......这满足了系统的授权方面,但会导致糟糕的用户体验。

那么人们通常如何处理这个问题?

你自己回答你自己的问题,真的。为用户设置多个角色比在控制器上指定所有可能的角色更容易,因为角色存储在您的数据库中并且可以随时操作,但是将角色添加到控制器需要重建和重新部署您的项目。

另外,并非所有管理员都应该有权访问所有区域。我见过允许管理员创建用户和修改密码但不允许查看个人医疗记录的系统。

所以是的,我非常建议为您的用户分配多个角色 - 在更长的时间内维护它会更容易 运行。

编辑: 所以你想要超级管理员用户可以访问任何地方而不必在所有控制器中特别提到它?听起来您需要重写 AuthorizeAttirbute 以添加始终获得授权的管理员角色。

像这样:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // The user is not authorized => no need to go any further
            return false;
        }


        if(httpContext.User.IsInRole("Admin"))
        {
            return true;
        }

        return base.AuthorizeCore(httpContext);
    }
}

然后用这个新属性装饰你所有的控制器:

[MyAuthorize(Roles = "User")]
public ActionResult MySuperAction()
{
    ...
}