linux权限设计的思考

linux权限设计

从chmod命令开始

相信用过linux的都执行过这样一条命令:chmod 754 xxx
在linux文件系统中,有三个角色组,分别是:所有者(Owner)、组(Group)、其他用户(Other)。
每个组权限中又分别包含: r(读)、w(写)、x(执行) 三种权限,每个权限有一个对应的数字值:r(4)、w(2)、x(1)。
可以通过将这三种权限数字相加得到角色的权限值,例如,读写权限可以表示为 6(4+2+0)。
回到上面的命令chmod 754,7,5,4 每个数字分别对应这三个所属角色权限,7表示所有者具备可执行权限,中间的5表示组具备可执行权限,最后一个4表示其它用户只具备权限。
linux权限设计的思考_第1张图片
linux权限设计的思考_第2张图片

❓ 这几个权限的数字为什么是r(4)、w(2)、x(1),而不是3,2,1?

用10进制的角度来看,这几个数字的规律分别是2⁰=1,2¹=2,2²=4。

进一步转换成二进制可以用001,010,100来表示。

再回过头来看权限,权限要么是可以,要么是不可以,可以用一个Boolean来表示,也就是要么是0,要么是1。如果用000来表示3种权限,第一个0表示执行权限,第二个0表示权限,第三个0表示权限,那么表示可读写但不可执行就可以用110来表示,而110转换成10进制恰好就等于6,以此类推,111=7(可读写执行),101=5(可读可执行不可写)。

所以用三个二进制位就包含了读,写和执行权限的所有组合情况,用8或10进制来看就是它们可以组合成[1,7]之间任意一个数字。

除了chmod 754 这种纯数字授权,还有一个chmod +x命令

chmod +x其实等价于chmod a+x,这里面的a其实是all的意思,其它的还有u(所有者),g(组),o(其它用户),它的作用是给三组权限全部加上执行权限。假设xxx文件当前权限是763,用二进制表示111 110 011,a+x就是已经有x的不变,没有的加上x执行权限,这与二进制的或( | )运算符的定义不谋而合:对应位置上的两个二进制位中至少有一个为1时,结果位为1;否则为0。这个计算过程用二进制的角度来看其实就是

7 | 1 = 111 | 001 = 111 = 7
6 | 1 = 110 | 001 = 111 = 7
3 | 1 = 011 | 001 = 011 = 3

当然,有+x,那就还有-x,移除权限。不难看出移除权限要做的就是对应位置上的两个二进制位中,如果对应位置都为1,结果位为0,否则取原二进制位的值

这里没有直接对应的二进制运算符可以一步到位满足计算需求,但依然是有办法的

同样以763为例

7 & (1 ^ 7) = 111 & (001 ^ 111) = 111 & 110 = 110 = 6
6 & (1 ^ 7) = 110 & (001 ^ 111) = 110 & 110 = 110 = 6
3 & (1 ^ 7) = 011 & (001 ^ 111) = 011 & 110 = 010 = 2

最终 763 - x = 662。


延申

假设有这样一个需求:查找一个手机号在哪些平台注册过,假设目前只有微信、QQ、抖音、小红书四个平台,将来或许还有微博,快手等。

常规表结构设计可能是phone,exists_wechat,exists_qq,exists_tiktok,exists_xhs这几个字段,后面如果增加其它的平台只能再继续增加表字段。但细心观察就会发现,后面这几个字段都是boolean值,也就是一个二进制位就能表示了。那么我们现在就可以先用四个二进制位来分别表示这4个平台,0000,从右往左第一位表示是否注册过微信,第二位表示是否注册过QQ,以此类推。那么表示该手机号只注册过QQ就可以表示成0010,如果只注册过小红书和QQ,那么就用0110来表示。

表结构就可以设计成phone, apps这两个字段,apps用一个10进制数字表示。

那么如何查询某个手机号是否在某个app平台注册过呢?假设我们需要查询在抖音注册过的手机号,

已知我们现在总共有4个app平台,用二进制表示就是0000,其中从右往左,第3个是表示抖音的位置,也就是要找到值包含?1?? 的数字,不难发现 [4,5,6,7,12,13,14,15] 这些都是的。最终需要的查询SQL就应该是select * from tablename where apps in (4,5,6,7,12,13,14,15) 。那用什么方法才能计算出是这几个数字呢?方法也很简单

首先定义一个掩码mask = 1 << n。n(从0开始)是你想找的位下标为1的值,比如n=2,那么mask = 1 << 2 = 0001 << 2 = 0100 = 4。

将1~15分别与4 做 & 运算,只有第2位为1的情况下,&运算的结果才不为0。用代码实现如下:

    /**
     * 查找第index位上为1的数字
     *
     * @param index 位下标,从右往左第0位开始
     * @return int[]
     * @author 敖癸
     * @since 2024/1/26 - 10:02
     */
    public static int[] findApps(int index) {
        int mask = 1 << index;
        return IntStream.range(1, 16).filter(i -> (i & mask) != 0).toArray();
    }

    public static void main(String[] args) {
        int[] apps = findApps(2);
        for (int i: apps){
            System.out.print(i+",");
        }
    }

// 输出结果:4,5,6,7,12,13,14,15

实体类设计

@Data
public class PhoneApp{
  private String phone;
  private Integer apps;

  /**
   * 添加app
   *
   * @param index 位下标 0:微信,1:QQ,2:抖音,3:小红书
   * @author 敖癸
   * @since 2024/1/26 - 10:21
   */
  public void addApps(int index){
      int mask = 1 << index;
      this.apps |= mask;
  }
}

你可能感兴趣的:(linux,java,运维)