ade*_*lin 38 c# asp.net-mvc access-control asp.net-core
我正在尝试使用aspnet核心实现基于权限的访问控制.为了动态管理用户角色和权限(create_product,delete_product等),它们存储在数据库中.数据模型类似于http://i.stack.imgur.com/CHMPE.png
在aspnet核心之前(在MVC 5中)我使用AuthorizeAttribute下面的自定义来处理这个问题:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在下面的动作方法中使用它:
[HttpGet]
[CustomAuthorize(PermissionEnum.PERSON_LIST)]
public ActionResult Index(PersonListQuery query){ }
Run Code Online (Sandbox Code Playgroud)
另外,我在视图中使用HttpContext.Items ["CUSTOM_USER"]来显示或隐藏html部分:
@if (CurrentUser.HasPermission("<Permission Name>"))
{
}
Run Code Online (Sandbox Code Playgroud)
当我决定切换aspnet核心时,我的所有计划都失败了.因为没有虚拟OnAuthorization方法AuthorizeAttribute.我尝试了一些解决问题的方法.这些是:
使用新的基于策略的授权(我认为它不适合我的场景)
使用自定义AuthorizeAttribute 和AuthorizationFilter(我读这篇文章 /sf/answers/2510446011/但我无法正确更改)
使用自定义中间件(如何获取AuthorizeAttribute当前操作?)
使用ActionFilter(出于安全目的,它是否正确?)
我无法确定哪种方式最适合我的场景以及如何实现它.
第一个问题:MVC5实施不好吗?
第二个问题:你有任何建议实施aspnet核心吗?
Tse*_*eng 55
根据评论,这里有一个关于如何使用基于策略的授权的示例:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
并在您的Startup课程中注册:
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>();
Run Code Online (Sandbox Code Playgroud)
最后在控制器中
[HttpGet]
[Authorize(Policy = PermissionEnum.PERSON_LIST.ToString())]
public ActionResult Index(PersonListQuery query)
{
...
}
Run Code Online (Sandbox Code Playgroud)
该解决方案的好处是,你也可以有一个要求,即多个处理程序,如果第一个成功的第二处理器能够确定这是一个失败,你可以使用它以资源为基础的授权费多大力量.
基于策略的方法是ASP.NET核心团队执行此操作的首选方法.
来自blowdart:
我们不希望您编写自定义授权属性.如果你需要这样做我们做错了什么.相反,你应该写授权要求.
| 归档时间: |
|
| 查看次数: |
30073 次 |
| 最近记录: |