权限认证-基于紧凑的数据结构

1.背景原因

假设我们有一批用户的权限信息,分为4类权限A,B,C,D。如何设计一种能够快速识别身份权限的数据结构呢?
首先我们先要对用户与权限建立一种映射关系,也就是 用户-权限信息。

用户信息
权限信息

我们可以采用Key-value的形式进行存储,由于我们主要是做权限认证,所以先调整个方向。 权限信息作为key, 用户表示作为value。
首先我们可以想到用HashMap来存储,HashMap<用户信息,权限信息>,接下来就是设置权限信息的格式了,我们可以先简单的定义用户信息 就是一个 long类型的id,权限信息就是一串字符串,由“权限标识“”和“_”组成,例如这样 “A_B” 这就代表有2中权限A,B.

用户信息 ID
权限信息 A_B

但是这样有个问题,如果我们需要对某一类拥有指定权限的用户进行筛选就很麻烦。
假设现在有N个用户 M个方法
首先,我们先要遍历N个用户,然后对每一个用户的权限信息根据"_"字符进行拆分,然后在拆分的方法数组中进行遍历,从而找到特定用户。所耗费的次数为M * N。

可以明显的感觉到N其实是多余的。但是由于我们权限信息的数据格式设计的不合理,导致了我们需要进行这个N次比较。接下来我们就要想办法对权限信息的数据格式进行优化,使它1次就可以比较出是否含有指定权限。

一种紧凑的数据结构,就是位。 我们将权限信息用long这种类型来记录,而我们知道long一共有64位,那么我们就可以用它来表示64中状态。

2.解决与实现

一个简单的例子,
先定义权限信息

/**
 * @author: TangFenQi
 * @description: 定义一些权限枚举
 * @date:2020/1/16 15:45
 */
public enum AuthEnum {

  ADD(1 << 5),
  UPDATE(1 << 4),
  SELECT(1 << 3),
  DELETED(1 << 2);

  //权限值
  @Getter
  private long value;

  AuthEnum(long value) {
    this.value = value;
  }

}

下面分别来展示 权限的增加,删除,查询,包含如何做。

用来保存用户与权限信息的关联关系

private Map<Long, Long> AUTH_MAP = new HashMap<>();

1.增加

    private synchronized void add(long id, long addValue) {
        if (!AUTH_MAP.containsKey(id)) {
            AUTH_MAP.put(id, addValue);
        } else {
            long userValue = AUTH_MAP.get(id);
            userValue = userValue | addValue;
            AUTH_MAP.put(id, userValue);
        }
    }

只需要将值相或就行了。

2.删除

    private synchronized void deleted(long id, long removeValue) {
        long userValue = AUTH_MAP.get(id);
        userValue = (removeValue & userValue) ^ userValue;
        AUTH_MAP.put(id, userValue);
    }

删除比较麻烦的一点就是,有可能传入的权限你本来就没有,所以不能直接异或,先要相与把不存在的权限位给归0,然后在异或将对应位置归0.

3.是否包含权限

    private boolean contain(long id, long value) {
        long userValue = AUTH_MAP.get(id);
        long compareValue = userValue & value;
        return compareValue == value;
    }

进行相与,如果包含则其结果值就等于请求值。

4.获取用户权限

    private List<AuthEnum> findAuth(long id) {
        Long value = AUTH_MAP.get(id);
        List<AuthEnum> authEnums = new ArrayList<>();
        for (AuthEnum authEnum : AuthEnum.values()) {
            if ((authEnum.getValue() & value) == authEnum.getValue()) {
                authEnums.add(authEnum);
            }
        }
        return authEnums;
    }

我这定义了一个枚举,枚举里面的值就是权限的值。

3.总结

像这种紧凑的数据类型在实际的使用场景下还是有不错的发挥的,算是一种小技巧把。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐芬奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值