我目前面临的情况是,我正在用特定的授权属性来装饰我的HttpPost Controller操作方法,并在HttpGet中指定相同的规则,以确保在我的视图中没有某些功能可用。
是否有最佳实践或更好的解决方案,以便我可以在一个地方指定实际的业务规则,以启用DRY,而不进入代码爆炸的情况,即对每个规则都有一个特定的授权属性。
我目前的情况如下:
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,例如:
@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>
}
发布于 2014-07-03 22:37:52
是的,肯定有一种方法可以将业务逻辑从授权逻辑中分离出来,然后进行干涸。该区域称为外部化授权管理(EAM) (参见加特纳定义)。
要实现EAM,您需要使用的不仅仅是角色。您需要使用属性,其中属性本质上只是一个键值对,例如citizenship=Canadian
、clearance=SECRET
、department=sales
.
仅仅扮演角色是不够的。若要引用注释中先前共享的文章,请执行以下操作:
基于角色的授权检查有什么问题? 大量基于角色的检查已经创建了授权系统,那么它们有什么问题呢?很多事情,包括文档和耦合、建模和封装问题,以及需求的增长和变化。
基于角色的授权(也称为基于角色的访问控制( RBAC) )不够灵活,无法表达丰富的授权方案。您需要转到ABAC,即由NIST定义的基于属性的访问控制模型。
使用ABAC,您可以轻松地实现规则,如:
在ABAC中你可以表达什么是没有限制的。
实现ABAC的事实上的标准和技术是XACML,eXtensible访问控制标记语言.XACML定义:
在XACML中,所有策略都集中在一个位置。其中一些好处包括:-加快开发时间:您不再需要在应用程序中编写授权代码(if/ use )--更好的安全性:您可以在所有应用程序之间使用相同的策略,无论是语言还是技术。因此,我的回答并不局限于.NET --更好的审计能力:如果您将authZ逻辑移到基于中心策略的点上,那么检查它们就更容易实现DRY原则。
这些只是一些可以得到的好处。
有几种开放源码和供应商解决方案,如:
大卫。
发布于 2014-07-05 00:37:27
我过去处理这个问题的方法是创建一个抽象。不要引用允许执行任务的角色,而是引用包含允许执行任务的角色的字符串常量。就像这样:
public class Role
{
public const string DeleteRoles = "Administrator, role2, role3";
....
}
然后创建一个可以解释这些字符串常量的方法(我将其放在自定义原则中):
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()方法使用这些字符串常量:
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;
}
}
您在操作方法中使用的方法如下:
[HttpPost]
[CustomAuthorize(Roles = Role.DeleteRoles)]
public ActionResult Delete(int id)
{
/// do stuff
}
然后在视图中可以直接使用IsInRoles()方法:
@if(CustomPrincipal.Current.IsInRoles(Role.DeleteRoles))
{
<th>Delete record</th>
}
您可以通过各种方式实现这一点,但关键是抽象。
https://stackoverflow.com/questions/24562898
复制