混淆id的一种方法
admin
2023-07-31 00:46:12
0

众所周知,在web应用的API中,总是会出现数据库item的id。比如GET /posts/1表示获取id为1的文章内容。这样做十分简洁,但存在被人爬数据的风险。比如我可以大致猜测或者试一下id的范围,1,2,3…10000这样迭代地爬数据。如果服务器不做访问限制,很轻易就能把所有数据就能爬下来。而且,这样的数字id也会暴露一些信息,比如id小的一般是更早创建的。

所以要对id进行混淆,混淆有这么几个特点:

  1. 它是一个无符号整数到字符串的一一对应的函数
  2. 双向的,混淆之后可以恢复,所以不能用hash
  3. 不表现出递增的特征
  4. 不用像加密那样强,也不用有密钥
  5. 没有整数范围的限制。这一条是我加的,google能搜到很多id混淆的方法但它们可能要求id在2^32-1之内,比如对2^32求一个multiplicative inverse,这是一个不错的方法但因为这个限制我没有采用它。

最简单的一个方法是找一个比较大的数字进行异或,比如1-10跟1093420374进行异或的结果是这样的:

1234567891011 1 : 10934203752 : 10934203723 : 10934203734 : 10934203705 : 10934203716 : 10934203687 : 10934203698 : 10934203829 : 109342038310: 1093420380 

但这比较容易被人猜出是异或,需要再加上别的操作

我看到的一个比较好的方法也是我目前在用的是:

  1. 对id求个hash,取前16字节,作为segment1
  2. 对segment1求hash,取前8字节,作为segment2
  3. 将segment2转换为整数,加上id,再变回byte array
  4. 将segment1和segment2连接起来再求个hash,取前8字节,作为segment3(用于恢复时的验证)
  5. 连接segment1、2、3,做base64,得到混淆后的id

恢复的时候只用

  1. base64解码
  2. 取前16字节得到segment1,后8字节得到segment3,剩余字节是segment2
  3. 验证hash(segmemt1+segment2)是否等于segment3
  4. int(segment2)-int(hash(segment1))得到id

这用python实现比较方便,因为python的整数可以无限大,代码是这样的

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 class Obfuscator:    _head_bytes = 16    _mid_bytes = 8    _tail_bytes = 8     @staticmethod    def bytearray_to_int(byte_arr):        return int.from_bytes(byte_arr, byteorder=\’big\’)     @staticmethod    def int_to_bytearray(num):        assert isinstance(num, int) and num >= 0        if num == 0:            return b\’0\’        result = []        while num > 0:            d, m = divmod(num, 256)            result.append(m)            num = d        return bytes(result[::1])     @classmethod    def obfuscate(cls, uid):        if not uid:            return \’\’        uid_bytes = cls.int_to_bytearray(uid)        seg1 = hashlib.sha1(uid_bytes).digest()[:cls._head_bytes]         seg2 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]        seg2 = cls.int_to_bytearray(uid + cls.bytearray_to_int(seg2))         seg3 = hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes]         return base64.urlsafe_b64encode(seg1 + seg2 + seg3).decode()     @classmethod    def restore(cls, obscure_str):        if not obscure_str:            return 1        seg_bytes = base64.urlsafe_b64decode(obscure_str)        seg1 = seg_bytes[:cls._head_bytes]        seg2 = seg_bytes[cls._head_bytes:cls._tail_bytes]        seg3 = seg_bytes[cls._tail_bytes:]         if hashlib.sha1(seg1 + seg2).digest()[:cls._tail_bytes] != seg3:            return 1        seg1 = hashlib.sha1(seg1).digest()[:cls._mid_bytes]        return cls.bytearray_to_int(seg2) cls.bytearray_to_int(seg1) 


相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...