众所周知,在web应用的API中,总是会出现数据库item的id。比如GET /posts/1
表示获取id为1的文章内容。这样做十分简洁,但存在被人爬数据的风险。比如我可以大致猜测或者试一下id的范围,1,2,3…10000这样迭代地爬数据。如果服务器不做访问限制,很轻易就能把所有数据就能爬下来。而且,这样的数字id也会暴露一些信息,比如id小的一般是更早创建的。
所以要对id进行混淆,混淆有这么几个特点:
最简单的一个方法是找一个比较大的数字进行异或,比如1-10跟1093420374进行异或的结果是这样的:
1234567891011 | 1 : 10934203752 : 10934203723 : 10934203734 : 10934203705 : 10934203716 : 10934203687 : 10934203698 : 10934203829 : 109342038310: 1093420380 |
但这比较容易被人猜出是异或,需要再加上别的操作
我看到的一个比较好的方法也是我目前在用的是:
恢复的时候只用
这用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) |
上一篇:python实现地址分布可视化
下一篇:Python socket编程