如何实现基于角色的访问控制与Asp.Net核心权限 [英] How to implement Permission Based Access Control with Asp.Net Core

查看:295
本文介绍了如何实现基于角色的访问控制与Asp.Net核心权限的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现与ASPNET核心权限的访问控制。用于动态地管理用户角色和权限(create_product,delete_product等),它们被存储在数据库中。数据模型是如 http://i.stack.imgur.com/CHMPE.png

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 for my scenerio)

使用自定义 AuthorizeAttribute AuthorizationFilter (我读到这
发布 http://stackoverflow.com/a/35863514/5426333 ,但我不能改变它正常)

Using custom AuthorizeAttribute and AuthorizationFilter(i read this post http://stackoverflow.com/a/35863514/5426333 but i couldn’t change it properly)

使用自定义的中间件(如何获得 AuthorizeAttribute 电流
行动?)

Using custom middleware(how to get AuthorizeAttribute of current action?)

使用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)
{
    ...
}

这种解决方案的好处是,你也可以有多个处理程序的要求,也就是说,如果第一次成功,第二个处理程序可以判断这是一个失败,你可以用的resource授权费多大力量的。

的基于策略的方法是preferred方式由ASP.NET核心团队去做。

The policy based approach is the preferred way to do it by the ASP.NET Core team.

通过 blowdart

我们不希望你编写自定义授权属性。如果你需要做的,我们已经做了一些错误。相反,你应该写授权要求。

We don't want you writing custom authorize attributes. If you need to do that we've done something wrong. Instead you should be writing authorization requirements.

这篇关于如何实现基于角色的访问控制与Asp.Net核心权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆