如何在.netcore 上实现 Rbac 权限管理

 

 

如何在.netcore 上实现 Rbac 权限管理

1、.netcore 的权限系统

     .netcore 的权限系统是将认证系统和授权系统分两步实现的

1
2
3
4
5
6
7
8
9
10
11
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
       ...
            
       // 认证系统
       app.UseAuthentication();
       // 授权系统
       app.UseAuthorization();
 
       ...
 }   

 

认证系统:解决用户是谁的问题。

当用户完成 Login 操作后,用户携带的相关信息通过 Claims 直接存到了 HttpContext.User.Identity 中。

授权系统:解决该用户有没有对应的权限问题。

2、.netcore 上的自定义授权实现

可以在 controller 上加 attribute 的方式,通过实现 IAsyncAuthorizationFilter 接口获得授权执行的入口。

1
2
3
4
5
6
7
8
9
10
11
12
13
[Authorize]
 public class HomeController : Controller
 {
     ...
 
     [PermissionFilter]
     public IActionResult Privacy()
     {
         return View();
     }
 
     ...
 }

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
  public class PermissionFilter : Attribute, IAsyncAuthorizationFilter
  {
      public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
      {
          var url = context.HttpContext.Request.Path;
          var authorizationService = context.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
          var authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null, new PermissionAuthorizationRequirement(url));
          if (!authorizationResult.Succeeded)
          {
              context.Result = new ForbidResult();
          }
      }
  }

  

其中 authorizationService 是自定义的授权类,需要在 Startup 文件中的 ConfigureServices 函数中提前注册好,而 PermissionAuthorizationRequirement() 是授权类需要用到的参数类

1
2
3
4
5
6
public void ConfigureServices(IServiceCollection services)
   {
       ...
 
       services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();
   }

  

下面的代码是 PermissionAuthorizationHandler 的具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class PermissionAuthorizationRequirement : IAuthorizationRequirement
{
    public PermissionAuthorizationRequirement(string path)
    {
        Path = path;
    }
 
    public string Path { get; set; }
}
 
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionAuthorizationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement)
    {
        if (context.User != null)
        {
            if (context.User.IsInRole("admin"))
            {
                context.Succeed(requirement);
            }
            else
            {
                var userIdClaim = context.User.FindFirst(_ => _.Type == ClaimTypes.NameIdentifier);
                if (userIdClaim != null)
                {
                    //if (_userStore.CheckPermission(int.Parse(userIdClaim.Value), requirement.Path))
                    {
                        context.Succeed(requirement);
                    }
                }
            }
        }
        return Task.CompletedTask;
    }
}

 

通过在 HandleRequirementAsync 函数中,返回

1
context.Succeed(requirement)

表示授权通过。

 

3、Rbac 授权实现

通过 1和2 ,我们找到了实现自定义授权的方式,下面看看 Rbac 授权如何实现。

 Rbac 是通过把 permission 列表配给 role ,然后把多个 role 分配给用户。

对于 controller 上的函数 Path ,正好就是这里的 permission,所以授权就是检测用户是否有 Path 的授权。

1
CheckPermission(int.Parse(userIdClaim.Value), requirement.Path)

  

4、参考资料

OAuth2.0究竟是个啥?

OAuth 2.0 系列教程

 ASP.NET Core 认证与授权[5]:初识授权

在ASP.NET Identity 2.0中使用声明(Claims)实现用户组

 扩展IdentityRole和IdentityUser(Extending IdentityRole and IdentityUser)

如何创建UserManager的实例(How do i create an instance of UserManager)

扩展ASP.NET Identity使用Int做主键

 

posted @   神游虚空  阅读(1586)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示