【实战 Ids4】║ 认证中心之内部加权

本期配套视频:

https://www.bilibili.com/video/BV1sJ41197af?p=9

(昔我往矣,杨柳依依,今我来思,雨雪霏霏)

1、为什么需要在认证内部加权

我们知道,认证中心的作用就是用来保护我们的资源服务器,所以说认证中心是一个保护者,当然,他在保护其他客户端的时候,也需要对自己进行保护,举例来说:

我的Ids4项目中,有用户角色信息管理,客户端数据管理等等,这些不可能让普通的登录用来来访问的

因此我们同样需要在认证中心内部实现加权处理,用来保护某些页面或者说某些数据的安全性不被恶意攻击或访问。

当然除了不让普通用户访问,我们也同样为了区分公司内部管理员的身份和权限,也同样需要如此,超级管理员有很高的权限,可以处理任意数据。

这就是为什么我们需要在认证中心内部进行权限管理的原因。

2、常见的加权方式有哪几种

这个问题不仅仅是在认证中心,其实在任何的项目中,包括资源服务器中,我们也是常用这几种权限处理方式,多数是基于角色控制的RBAC模式

这几种我都使用过,也都是各有利弊的,我在资源服务器Blog.Core中,用的是第④种,而这次在认证中心Blog.IdentityServer中,使用的是第③种。

第四种是最复杂的,保存到数据库,可以实现动态的策略授权,我们通过配置数据库,就可以针对任意一个页面或者API进行控制,但是在认证中心中,有些过于复杂了,故暂时不用。

第一种是无状态的,任意登录的用户都能访问,起不到控制的作用,仅仅是起到防止那些访客任意访问的作用,故舍弃。

第二种其实和第三种是一样的代码,我举例来说明:

  services.AddAuthorization(options =>
  {
      options.AddPolicy("Admin", policy => policy.Requirements.Add(new ClaimRequirement("rolename", "Admin")));
      options.AddPolicy("SuperAdmin", policy => policy.Requirements.Add(new ClaimRequirement("rolename", "SuperAdmin")));
  });


  services.AddSingleton<IAuthorizationHandler, ClaimsRequirementHandler>();


从代码中,我们可以看到,我虽然创建了一个简单的策略,但是逻辑却是获取rolename角色名,判断各自的角色,那我为啥不直接用第二种呢:

这样岂不是更简单,也不用写处理器等逻辑了,直接这么写一下即可。

下边我会讲为什么没有用这个。

3、你的资源服务器是如何加权的

你可能会好奇,今天说的是认证中心的加权,为啥又说到了资源服务器?是不是多此一举了,并不是,其实我们写的每一行代码都应该考虑下,是否对其他的有影响,是否对其他的项目有关联,今天说的认证中心也是,我先给大家回忆一下Blog.Core的资源服务器是如何权限控制的。

Blog.Core中,用到的是上面说的第四种,复杂数据库的策略授权,我们把数据都配置到了数据库中,通过角色+菜单+接口的三方约束,来实现当前用户是否有权利访问当前接口

细心的你可能发现了,这个多对多的关系表中,我们用到的是RoleId,那这个Id是从哪里来的,肯定是从Ids4认证中心来的,毕竟用户是在那里统一登录注册。

那是如何传递过来的,肯定是Token,进一步说明,是Token中的Cliams声明,那我们继续往前推,这个声明是从哪里配置的?是这里:

这里用SeedData来举例,生成种子数据的时候,我们把角色Id赋给了JwtClaimTypes.Role的Cliams节点,这个是一个常量,也就等于是role这个节点。

这样的话,我们Token中的声明中的role节点,其实就是我们的角色Id,那上边反推的逻辑就成功了,我们再来总结下:

用户登录——>获取token——>携带roleid——>资源服务器HttpContext解析token

——>得到roleid——>根据roleid获取到指定的菜单mid和接口pid集合——>在策略授权中做逻辑判断。

看似一切很合理,但是却有一个问题,因为我Blog.Core是先开发的,所以假设我们的这个资源服务器代码不改的话,认证中心就有了一点儿小问题

4、认证中心的抉择

当前我们的角色信息是用的id,那认证中心就不能使用第二种方案了:

[Authorize(Roles = "AdminTest")]

因为这个时候,我们claims声明中,获取到的不是name,所以一定会失败,就算当前用户的角色真的是AdminTest,还是会失败:

这是因为按照这种方案,它只认识role这个节点,但是这个节点是id,没办法,我们只能这么写了:

虽然是通过了,但是看着还是感觉很不舒服,有点儿Bad Smell的意思。

所以这也就是我文章开头说的,我为啥要新建了一个策略,使用rolename节点作为策略的原因了:

 protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                ClaimRequirement requirement)
 {


     var claim = context.User.Claims.FirstOrDefault(c => c.Type == requirement.ClaimName);
     if (claim != null && claim.Value.Contains(requirement.ClaimValue))
     {
         context.Succeed(requirement);
     }


     return Task.CompletedTask;
 }

5、总结

今天虽然讲的是认证中心的加权处理,但是我们也要考虑到资源服务器的业务逻辑,

最终我还是采用的是:

资源服务器用roleid来配合菜单和接口id,实现权限分配;

认证中心采用策略方案,通过rolename来对页面进行权限控制;

到此结束,Ids4实战也告一段落了,很有意思也很能锻炼人思维逻辑的一个框架,建议大家好好学习,不可中途放弃,加油。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值