ASP.NET身份中角色与声明的最佳实践

问题描述 投票:81回答:3

我对claims中使用ASP.NETIdentity完全不熟悉,并想了解使用Roles and/or Claims的最佳实践。

经过这一切阅读后,我仍然有类似的问题......

问:我们不再使用角色吗? 问:如果是这样,为什么Roles仍然提供? 问:我们应该只使用索赔吗? 问:我们应该一起使用角色和声明吗?

我最初的想法是我们“应该”一起使用它们。我认为Claims是他们支持的Roles的子类别。

例如: 作用:会计 声明:CanUpdateLedger,CanOnlyReadLedger,CanDeleteFromLedger

问:他们打算互相排斥吗? 问:或者最好只去索赔并“完全符合”你的要求吗? 问:那么这里的最佳做法是什么?

示例:一起使用角色和声明 当然,你必须为此编写自己的属性逻辑......

[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
    // Do stuff here

    return View();
}

示例:完全限定您的索赔

[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
    // Do stuff here

    return View();
}
asp.net-mvc roles claims-based-identity
3个回答
70
投票

角色是一种符号类别,它将收集共享相同级别安全权限的用户收集在一起。基于角色的授权需要首先识别用户,然后确定用户被分配到的角色,最后将这些角色与授权访问资源的角色进行比较。

相反,声明是用户识别自己的权利。换句话说,“我被允许这样做,因为我有这个要求。”通常,基于声明的授权包含基于角色的授权。确切地说,角色成员资格是根据身份确定的,而身份只是对权利要求价值的一种权利。角色本质上是一种非常特殊的声明,即“因为我的用户名就是这个,我是这个角色的成员。因为我是这个角色的成员,所以我可以访问这个资源。”

您可以同时使用它们,也可以在某些情况下使用一种类型,在其他情况下使用另一种类型。它主要取决于与其他系统的互操作性和您的管理策略。例如,管理员管理分配给角色的用户列表可能比管理分配了特定索赔的用户更容易。声明在RESTful场景中非常有用,您可以在其中为客户端分配声明,然后客户端可以提出声明以进行授权,而不是为每个请求传递用户名和密码。


21
投票

正如@Claies完美解释的那样,声明可能更具描述性,并且是一种深层次的角色。我认为它们是你的角色ID。我有健身房,所以我属于会员角色。我也参加了跆拳道课程,所以我对他们有所要求;一个跆拳道ID。我的申请需要申报新角色以适应我的会员权利。相反,我在健身房可以做的每件特别事情都有ids;而不是许多新的会员类型。这就是为什么声称适合我。

Barry Dorrans有一个很好的解释视频,谈论使用声明而不是角色的优势。他还声明角色仍然在.NET中以实现向后兼容。该视频非常了解声明,角色,策略,授权和身份验证的工作方式。

你可以在这里找到它:ASP.NET Core Authorization with Barr Dorrans


6
投票

几十年来,我使用了各种身份验证和授权技术,我目前的MVC应用程序使用以下方法。

索赔用于所有授权。为用户分配了一个角色(可能有多个角色但我不需要这个角色) - 更多信息如下。

通常的做法是使用A ClaimsAuthorize属性类。由于大多数控制器操作都是CRUD,因此我在代码优先数据库生成中有一个例程,它迭代所有控制器操作,并为读取/编辑/创建/删除的每个控制器操作属性创建声明类型。例如。从,

[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]

为了在MVC视图中使用,基本控制器类提供视图包项

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // get user claims
            var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;

            if (user != null)
            {
                // Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
                List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();

                // set Viewbag with default authorisations on this controller
                ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
                ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
                ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
                ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
            }

            base.OnActionExecuting(filterContext);
        }

对于网站菜单和其他非控制器操作,我还有其他声明。例如。用户是否可以查看特定货币字段。

bool UserHasSpecificClaim(string claimType, string claimValue)
{
    // get user claims
    var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;

    if (user != null)
    {
        // Get the specific claim if any
        return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
    }

    return false;
}

public bool UserHasTradePricesReadClaim
{
    get
    {
        return UserHasSpecificClaim("TradePrices", "Read");
    }
}

那么角色适合哪里?

我有一个表将一个角色链接到(默认)一组声明。设置用户授权时,默认设置是向用户提供其角色的声明。每个用户可以拥有比默认值更多或更少的声明。为简化编辑,声明列表由控制器和操作(连续)显示,然后列出其他声明。按钮与一些Javascript一起使用来选择一组操作以最小化选择声明所需的“点击”。在“保存”上,将删除用户声明并添加所有选定的声明。 Web应用程序仅加载一次声明,因此任何更改都必须在此静态数据中提示重新加载。

因此,经理可以选择每个角色中的哪些声明以及用户在将其设置为角色后声明哪些声明以及默认声明。系统只有少量用户,因此管理这些数据非常简单

© www.soinside.com 2019 - 2024. All rights reserved.