首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MVC .NET中通用地方授权规则的最佳实践

MVC .NET中通用地方授权规则的最佳实践
EN

Stack Overflow用户
提问于 2014-07-03 20:36:45
回答 2查看 1.6K关注 0票数 2

我目前面临的情况是,我正在用特定的授权属性来装饰我的HttpPost Controller操作方法,并在HttpGet中指定相同的规则,以确保在我的视图中没有某些功能可用。

是否有最佳实践或更好的解决方案,以便我可以在一个地方指定实际的业务规则,以启用DRY,而不进入代码爆炸的情况,即对每个规则都有一个特定的授权属性。

我目前的情况如下:

代码语言:javascript
运行
复制
public class MyController
{

   [HttpGet]
   public ActionResult List()
   {
       // This action is responsible for showing the list of records.  Each record
       // can potentially have a delete link but this is only shown for Administrators

       var viewModel = new MyViewModel()
       {
          CanDeleteRecordRole = Role.Administrator, // Duplicated rule here
          // other properties
       }
   }

   [HttpPost]
   [Authorize(Role.Administrator)]
   public ActionResult Delete(int id)
   {
      /// do stuff
   }
}

public class Role
{
   public const string Administrator = "Administrator";
}

然后,在我看来,使用扩展方法,我将使用CanDeleteRecordRole,例如:

代码语言:javascript
运行
复制
@if(Model.DisplayIfAuthorized(Model.CanDeleteRecordRole))
{
   <th>Delete record</th>
}

// and for td columns

@if(Model.DisplayIfAuthorized(Model.CanDeleteRecordRole))
{
   <td>My action link here for deletion</td>
}
EN

回答 2

Stack Overflow用户

发布于 2014-07-04 06:37:52

是的,肯定有一种方法可以将业务逻辑从授权逻辑中分离出来,然后进行干涸。该区域称为外部化授权管理(EAM) (参见加特纳定义)。

要实现EAM,您需要使用的不仅仅是角色。您需要使用属性,其中属性本质上只是一个键值对,例如citizenship=Canadianclearance=SECRETdepartment=sales.

仅仅扮演角色是不够的。若要引用注释中先前共享的文章,请执行以下操作:

基于角色的授权检查有什么问题? 大量基于角色的检查已经创建了授权系统,那么它们有什么问题呢?很多事情,包括文档和耦合、建模和封装问题,以及需求的增长和变化。

基于角色的授权(也称为基于角色的访问控制( RBAC) )不够灵活,无法表达丰富的授权方案。您需要转到ABAC,即由NIST定义的基于属性的访问控制模型。

使用ABAC,您可以轻松地实现规则,如:

  • 用户可以编辑他/她拥有的文档
  • 用户可以查看属于同一部门的所有文档。
  • 如果文档是草稿,并且文档灵敏度等于或小于用户的权限,则具有角色审阅者的用户可以批准文档。

在ABAC中你可以表达什么是没有限制的。

实现ABAC的事实上的标准和技术是XACML,eXtensible访问控制标记语言.XACML定义:

  • 具有概念的授权体系结构
    • 到达决策的外部策略决策点 (PDP)
    • 保护应用程序/代码/ API并调用PDP的策略执行点
    • 用于检索附加属性和元数据的策略信息点 (PIP)。

  • 请求/响应方案:如何提出问题并得到答案,例如,Alice可以查看文件#123吗?
  • 用于实现策略的丰富的策略语言,如我之前给出的示例。

在XACML中,所有策略都集中在一个位置。其中一些好处包括:-加快开发时间:您不再需要在应用程序中编写授权代码(if/ use )--更好的安全性:您可以在所有应用程序之间使用相同的策略,无论是语言还是技术。因此,我的回答并不局限于.NET --更好的审计能力:如果您将authZ逻辑移到基于中心策略的点上,那么检查它们就更容易实现DRY原则。

这些只是一些可以得到的好处。

有几种开放源码和供应商解决方案,如:

大卫。

票数 1
EN

Stack Overflow用户

发布于 2014-07-05 08:37:27

我过去处理这个问题的方法是创建一个抽象。不要引用允许执行任务的角色,而是引用包含允许执行任务的角色的字符串常量。就像这样:

代码语言:javascript
运行
复制
public class Role
{
    public const string DeleteRoles = "Administrator, role2, role3";
    ....
}

然后创建一个可以解释这些字符串常量的方法(我将其放在自定义原则中):

代码语言:javascript
运行
复制
public class CustomPrincipal
{
    ...
    public bool IsInRoles(string roles)
    {
        bool authorized = false;

        var roles = roles.Split(',');
        foreach (var role in roles)
        {
            if (this.CurrentPrincipal.IsInRole(role)
            {
                authorized = true;
                break;
            }
        }

        return authorized;
    }
    ...
}

然后创建一个自定义授权属性,该属性可以通过IsInRoles()方法使用这些字符串常量:

代码语言:javascript
运行
复制
public class CustomAuthorizeAttribute: AuthorizeAttribute
{
    public string Roles { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (!isAuthorized)
        {
            return false;
        }

        isAuthorized = CustomPrincipal.Current.IsInRoles(this.Roles);

        return isAuthorized;
    }

}

您在操作方法中使用的方法如下:

代码语言:javascript
运行
复制
[HttpPost]
[CustomAuthorize(Roles = Role.DeleteRoles)]
public ActionResult Delete(int id)
{
    /// do stuff
}

然后在视图中可以直接使用IsInRoles()方法:

代码语言:javascript
运行
复制
@if(CustomPrincipal.Current.IsInRoles(Role.DeleteRoles))
{
   <th>Delete record</th>
}

您可以通过各种方式实现这一点,但关键是抽象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24562898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档