二进制是什么?-e操盘

二进制是什么?-e操盘

二进制是什么?

在数学和数字电路中指以2为基数的记数系统,以2为基数代表系统是二进位制的。这一系统中,通常用两个不同的数字0和1来表示。在计算机中,最常用的是二进制,因为组成计算机系统的逻辑电路通常只有开和关这两个状态,用0和1很好表示这两种状态。

二进制的使用

二进制可以控制系统的权限,说的简单点,即通过二进制0/1的位置来控制权限,因为某个功能要么有权限,要么没有权限

例如有一个场景:用户登录某个客户端(平板、手机、网页),要通过客户端的来源判定他是否有访问权限,我们可以通过二进制的权限位置,从最后一位往前(0位、1位、2位),设置3种权限:

可以访问平板:00000001

可以访问手机:00000010

可以访问网页:00000100

假设我们配置用户user1,可以通过平板和网页访问,即用二进制表示为00000101,用十进制表示为:5

当用户使用手机登录时,获取应用的权限00000010(一般每个应用调用登录接口都会携带一个appKey,这个appKey绑定了它所属的权限,根据appKey可查到对应的权限),十进制为:2,那怎么判定用户是否可以登录到当前应用呢?

通过&运算,功能权限 & 用户拥有的权限 == 功能权限?

即:2 & 5,转换为二进制:

  00000010
& 00000101
-------------
  00000000

&运算,只有两个位都是1,对应位才是1,

只有当2&5 == 2时,表示当前用户有手机登录权限。

二进制存储的优点

我们设计一个权限系统,一般都会基于RBAC模型rbac角色权限表设计,即用户-角色-权限,表设计如下:

常规做法,用户通过一个角色关联多个权限,数据存储如下:

这仅仅是一个角色,如果一个系统需要关联的角色很多,那么这张表将会存储大量的数据

通过使用二进存储可以大大减少数据量的存储,我们知道JAVA中Long类型可以转换为64位二进制,

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

如果把每一个位置来表示一个权限,除去最左边的符号位以外,可以表示63种权限人物立绘,即一个角色最多可以关联63种权限,如果一个角色关联了63种权限,那么我们只需要插入一条数据即可,但在复杂的系统中,63种权限肯定是不够的,可以通过设计一个权限空间来进一步区分,比如最初权限空间为0可以表示63种,当超过63种权限,权限空间递增,然后再可以表示63种权限,所以我们对之前的角色、权限表进行改造:

角色-权限新增/删除

当用户在界面上新增,或删除权限,我们又该如何更新二进制权限的数据?

增加权限

比如有一个角色,对应的权限空间为0,权限二进制是00001111,需要添加一个,权限空间为0,二进制为:00100000,二进制位置为5,使用二进制的“|”运算符,规则如下:

原二进制权限 | 要添加的二进制权限

通过二进制位得到要添加的二进制权限

1 > 3 得到 00000001,即将所在的权限位置移动到了最后一位音效,只要和1做 & 操作,得到的结果如果是1,那么表示包含了这条权限数据

根据权限查角色

SELECT
*
FROM
权限表 p
LEFT JOIN 角色-权限关联表 rp ON p.权限空间 = rp.权限空间
LEFT JOIN 角色表 r ON r.角色Id = rp.角色Id
WHERE
CONV(rp.权限二进制,2,10) >> p.权限二进制位 & 1 = 1
and p.权限名称 = ?

通过二进制存储数据的好处,大大降低了数据量,原来63条数据可以只用一条数据就可以代替,进行权限判断时,原来需要从几十甚至上百的数据一条一条判断,现在仅仅需要进行位运算就可以了,位运算一般比前面的逻辑高效的多。

但也有缺点,数据库存储的都是二进制,可读性降低了,如果项目交接给其它同事,还得对于权限空间和权限位置这些字段含义详细介绍rbac角色权限表设计,并且查询使用到了各种函数转换,这些字段的索引也失效了

总结:一般对于用户权限功能个数确定,比如一个供应商有几十万门店,用户、角色、权限数量不多,可以考虑使用二进制来控制权限提升效率、减少存储数据量。

文章来源:https://developer.aliyun.com/article/778501