需求场景

不知道你有没有遇到过平台对“用户-访问”方面控制的需求?也就是要求平台满足:

  1. 非公司用户访问平台,直接拒绝
  2. 公司用户,但不是同部门访问平台,需要额外添加权限才能访问
  3. 公司同部门用户,成功访问

上面是最简单的控制的要求,一般企业的平台都是必须要满足的。就依上述需求而言,我们的实现方式可以有哪些呢?

传统解决方案

这里的“传统”,不代表“大多数“平台的使用实现方式,仅是我见过的一个企业后台项目的鉴权模式(可能其他项目也这样?🤔)。这个项目的实现非常简单和直接。

用户在经过统一认证平台登录后,访问某部门的平台,鉴权中间件去判断用户名是否存在于数据库中,存在即放行,反之拦截。

这样其实已经解决了上面的三个需求,我们只需要将有资格访问的用户名存于数据库,就能达到基本的“用户-访问”控制。可如此简单的一种实现,是否对“企业”级别的后台要求过于低呢?

在我看来,这种实现确实简单,颠覆了我以往对"企业级"这三个字的看法。但仔细想想,最基本的用户登录已由统一认证平台处理,后续只需区分是否为同部门用户及特殊用户即可。如果平台不需要更细粒度的权限控制,这种方案完全够用——简单即是最好

注:一般公司用户都是在办公网环境下进行的,不是办公网无法访问和公司 IT 系统有关的东西!

新的解决方案

产品来了新的需求,要求平台有更细粒度的权限控制。如图:

平台需要确保用户访问的某个接口有权限!权限管理平台要求用户携带具体的 API + 请求资源,然后再进行判断。

对于这个新要求,传统的解决方式已经完全不适用,平台需要一个全新的解决方式,也就是本篇的主题:基于角色的访问控制(RBAC)

这里不对 RBAC 做更多的解释,想要了解更多的请看【参考】。

权限管理平台

不管实现如何,RBAC 模式大致遵循以下基本原则:

  • 为每个用户分配一个或多个角色
  • 为各个用户角色分配权限
  • 用户成为某一角色的有效成员,获得访问权限

然后分为三个模块:角色、操作组、资源

  • 角色:决定用户能够操作什么接口,同时还决定用户能拥有什么资源
  • 操作组:一堆操作的集合,可以简单理解为后端的接口
  • 资源:万物皆资源,游戏 id,应用,配置,函数等等

基于此设计的权限模型:

整体的鉴权流程:

流程说明:

  1. 请求入口:接收带有用户id、请求的 api 以及资源
  2. 获取用户绑定的角色:根据用户 id 查询其绑定的角色
  3. 获取角色绑定的操作组:获取该角色可以访问的接口组
  4. 判断api是否在操作组内
    • 否 → 拦截
    • 是 → 继续判断
  5. 判断操作组是否依赖资源
    • 否 → 放过
    • 是 → 获取用户+角色绑定的资源
  6. 判断请求资源是否在绑定列表中
    • 是 → 放过
    • 否 → 拦截

可以看到 RBAC 模式可以很好解决新的需求,达到更细粒度的权限控制和管理,只是会增加一定的开发/维护成本。

RBAC 也并非完美的权限控制模式,只是非常适合当下的场景:

  • 组织结构清晰,角色定义明确
  • 权限模型相对稳定
  • 需要合规审计的系统

此外,在实际应用中,有些用户和接口是不需要鉴权的,我们可以单独在配置里(数据库)维护一个白名单。

注:如果权限需求高度动态化、需要基于多维属性的复杂授权、资源级别的细粒度控制要求高,可能使用 ABAC(基于属性的访问控制) 模式会更好。

降级

在企业环境中,权限管理平台通常作为公共服务单独部署,供多个业务平台调用。这种架构下,权限服务一旦故障,将影响所有依赖它的业务系统。因此,我们需要设计合理的降级策略,确保权限服务不可用时,业务系统仍能在可控风险内继续运行。

这里的降级策略因平台重要性、ToB or ToC、使用人员数量、数据一致性等考虑其最佳实现方式。

在这里我给出一个基于本地缓存实现的降级策略:

这里面有几个要点:

  1. 构建缓存 KEY:user_id + api + resource,设置缓存 TTL
  2. 请求三次避免网络抖动问题
  3. 重试间隔(100ms)以及请求超时间隔(1s),参考平台情况
  4. 触发降级的条件必须是权限管理平台不可用(如超时、网络错误),而非业务逻辑返回的"无权限"或其他错误
  5. 宁可误拒用户,不可误放已取消权限的用户

方案对比

维度传统方案(白名单)RBAC 方案
实现复杂度中等
权限粒度用户级别接口 + 资源级别
维护成本中等
扩展性
适用场景简单访问控制细粒度权限管理

总结

权限系统的设计,本质上是在安全性可用性复杂度之间寻找平衡点。从白名单到 RBAC,再到 ABAC,每一步演进都是为了应对更复杂的业务场景,但切记:够用就好,过度设计是另一种浪费

参考