关于权限系统的一些思考
开始
权限系统无非是解决两个问题,Authentication(认证-你是谁)和 Authorization(授权-你能干什么)。
Authentication
认证的问题,很好理解,就是根据用户的身份凭据,计算出这个用户的身份信息。
而身份凭据,常见有 Token 和 Session,还有 Permanent Token(永久令牌)、Application password(应用专用密码)等。
这里可以延伸聊一下登录
问题,其实登录不应该算作 Authentication 范畴,登录只是一个 Action
,用于换取身份凭据的动作。没有登录这个工作,换种方式颁发身份凭据,难道权限系统就不能工作了吗?
Authorization
Authorization 又可以划分为三个问题来解决:
- 分配:赋予谁什么权限;
- 解决/计算:计算谁有什么权限;
- 判断:判断谁是否有某个权限;
分配
分配要考虑的问题有两个,一个是谁、一个是目标。因此分配要解决的问题就是:要给谁在什么目标上分配什么权限。
给谁?比如用户、用户组等,我们称为 Owner
。
什么目标?权限分配一定要有一个附着点,比如项目、公司、组织等,我们称为 AuthTarget
。
什么权限?为了分配上的方便,我们常常把一堆权限集称为 角色
,角色的作用仅仅是为了分配上的简洁,一般不用来做判断,什么原因,下文会解释。
我们一般推荐权限系统是模块独立于业务系统的,很简单,权限系统本来就是业务不相关的。我们只要将权限系统的 AuthTarget
和业务系统的资源做关联,就能驱动业务系统完成权限工作,而这个关联行为是权限系统关联业务系统,还是业务系统关联权限系统,或是单独关联,仁者见仁,智者见智。
解决
计算一个 Owner 有什么权限,并缓存起来。
这点主要是为了性能的考虑,如果在判断的时候再去计算 Owner 的权限,必将大大拖累业务系统的性能,而且一个 Owner 的权限大部分时间内都是不变的,因此缓存命中率特别高,特别适合缓存。
缓存的 Key 的是 Owner,Value 包括 权限 + AuthTarget。
判断
判断一个 Owner 是否有权限访问资源。
判断分为前端和后端,而判断的前提就是依赖 解决
中缓存的用户权限。
为什么不用 角色
来判断 Owner 是否能访问资源呢?如果诸多资源都用一个角色
判断,不方便扩展和拆分,更严重的是,随着时间推移,常常出现自己都预想不到的越权行为,因为到处都是基于某个角色的判断。那么我多定义一些角色呢?额。这不就变成了权限判断?
直接使用权限进行判断,可以为用户提供更精细的权限控制。安全系统设计的一个重要原则是“最小权限原则”(Principle of Least Privilege),即应尽可能只授予用户完成任务所需的最低权限。通过直接基于权限判断,可以更加严格地控制用户权限的分配,减少误授权的可能性。