问题描述
我试图实现与ASPNET核心权限的访问控制。用于动态地管理用户角色和权限(create_product,delete_product等),它们被存储在数据库中。数据模型是如
I am trying to implement permission based access control with aspnet core. For dynamically managing user roles and permissions(create_product, delete_product etc.), they are stored in the database. Data Model is like http://i.stack.imgur.com/CHMPE.png
在ASPNET核心(MVC中的5)我使用自定义的 AuthorizeAttribute
象下面这样来处理这个问题:
Before aspnet core (in MVC 5) i was using custom AuthorizeAttribute
like below to handle the issue:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
private readonly string _permissionName { get; set; }
[Inject]
public IAccessControlService _accessControlService { get; set; }
public CustomAuthorizeAttribute(string permissionName = "")
{
_permissionName = permissionName;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
var user = _accessControlService.GetUser();
if (PermissionName != "" && !user.HasPermission(_permissionName))
{
// set error result
filterContext.HttpContext.Response.StatusCode = 403;
return;
}
filterContext.HttpContext.Items["CUSTOM_USER"] = user;
}
}
然后我使用它的操作方法如下图所示:
Then i was using it in action method like below:
[HttpGet]
[CustomAuthorize(PermissionEnum.PERSON_LIST)]
public ActionResult Index(PersonListQuery query){ }
此外,我是使用HttpContext.Items [CUSTOM_USER]在视图中显示或隐藏的HTML部分:
Additionally, i was using HttpContext.Items["CUSTOM_USER"] in views to show or hide html part:
@if (CurrentUser.HasPermission("<Permission Name>"))
{
}
当我决定改用ASPNET核心,我所有的计划失败了。因为当时在 AuthorizeAttribute
无虚 OnAuthorization
方法。我尝试了一些方法来解决问题。这些都是如下:
When i decided to switch aspnet core, all my plan was failed. Because there was no virtual OnAuthorization
method in the AuthorizeAttribute
. I tried some ways to solve problem. Those are below:
-
使用新的基于策略的授权,(我认为这是不适合
我之情况)
Using new policy based authorization(i think it is not suitable formy scenerio)
使用自定义 AuthorizeAttribute
和 AuthorizationFilter
(我读到这
发布,但我不能改变它正常)
Using custom AuthorizeAttribute
and AuthorizationFilter
(i read thispost http://stackoverflow.com/a/35863514/5426333 but i couldn’t change it properly)
使用自定义的中间件(如何获得 AuthorizeAttribute
电流
行动?)
Using custom middleware(how to get AuthorizeAttribute
of currentaction?)
使用ActionFilter(它是正确的,为了保密?)
Using ActionFilter(is it correct for security purpose?)
我不能决定哪种方式最适合我之情况以及如何实现它。
I couldn’t decide which way is the best for my scenerio and how to implement it.
第一个问题:是否MVC5执行不好的做法
First question: Is MVC5 implementation bad practice?
第二个问题:你有什么建议实施ASPNET核心
Second question: Do you have any suggest to implement aspnet core?
推荐答案
根据的评论,在这里如何使用基于策略的授权一个例子:
Based on the comments, here an example on how to use the policy based authorization:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionBasedRequirement(PermissionEnum permission)
{
Permission = permission;
}
public PermissionEnum Permission { get; }
}
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IUserPermissionsRepository permissionRepository;
public PermissionHandler(IUserPermissionsRepository permissionRepository)
{
if(permissionRepository==null)
throw new ArgumentNullException(nameof(permissionRepository));
this.permissionRepository = permissionRepository;
}
protected override void Handle(AuthorizationContext context, PermissionRequirement requirement)
{
if(context.User==null)
{
// no user authorizedd. Alternatively call context.Fail() to ensure a failure
// as another handler for this requirement may succeed
return null;
}
bool hasPermission = permissionRepository.CheckPermissionForUser(context.User, requirement.Permission);
if (hasPermission)
{
context.Succeed(requirement);
}
}
}
而在你的启动
类进行注册:
services.AddAuthorization(options =>
{
UserDbContext context = ...;
foreach(var permission in context.Permissions)
{
// assuming .Permission is enum
options.AddPolicy(permission.Permission.ToString(),
policy => policy.Requirements.Add(new PermissionRequirement(permission.Permission)));
}
});
// Register it as scope, because it uses Repository that probably uses dbcontext
services.AddScope<IAuthorizationHandler, PermissionHandler>();
终于在控制器
[HttpGet]
[Authorize(Policy = PermissionEnum.PERSON_LIST.ToString())]
public ActionResult Index(PersonListQuery query)
{
...
}
这种解决方案的好处是,你也可以有多个处理程序的要求,也就是说,如果第一次成功,第二个处理程序可以判断这是一个失败,你可以用的的。
的基于策略的方法是preferred方式由ASP.NET核心团队去做。
The policy based approach is the preferred way to do it by the ASP.NET Core team.
通过:
我们不希望你编写自定义授权属性。如果你需要做的,我们已经做了一些错误。相反,你应该写授权要求。
这篇关于如何实现基于角色的访问控制与Asp.Net核心权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!