这种方法通常被称为 “双向映射” 或 “可逆混淆”。它的核心思想是:不存储,只计算。
你不需要在数据库里存额外的 UUID 字段,也不需要改表结构,只需要在接口层加一道“加解密”的工序。
核心原理:Hashids 或 自定义加解密
最简单的实现不是用复杂的 AES 加密(那样太重了),而是使用 Hashids 算法,或者简单的 异或(XOR) + Base62 转换。
- 对外(加密/编码):当数据从后端返回给前端或外部程序时,把自增 ID
12345转换成类似k4R9z的字符串。 - 对内(解密/解码):当外部程序带着
k4R9z来请求数据时,后端把它转回成数字12345,然后用这个数字去数据库查询。
改动成本分析
改动点 1:序列化/输出层(最小侵入)
- 做法:如果你使用的是 REST API,可以在返回 JSON 的时候,拦截 ID 字段。
- 代码示意(伪代码):
# 原来返回 {"id": 12345, "name": "test"} # 现在返回(使用hashids) {"id": hashids.encode(12345), "name": "test"} # 输出: {"id": "k4R9z", "name": "test"} - 优点:只需要改 API 的输出逻辑,数据库查询逻辑完全不动。
改动点 2:控制器/输入层
- 做法:在接收到请求时(如
/api/item/k4R9z),先解码。 - 代码示意:
# 接收到 id_str = "k4R9z" real_id = hashids.decode(id_str) # 转回 12345 # 后续逻辑完全不变,还是用 real_id 去查库
优缺点分析
优点:
- 零存储成本:不需要改数据库,不需要加字段,不需要建映射表。
- 改动相对少:只需要在数据进出的“网关”处处理,业务核心逻辑(增删改查)不需要大改。
- 防遍历效果好:外部看到的是一串乱码,无法通过
+1来猜解其他数据。
缺点/注意事项:
- 防破解能力一般:Hashids 是一种混淆,不是高强度加密。如果攻击者知道你用的是 Hashids 且知道你的“盐(salt)”,是可以反向推导的。但对于防止普通爬虫和“ID预测”足够了。
- 分页处理:如果你用
id > last_id分页,前端传回来的last_id是加密字符串,你需要先解密成数字,再拼 SQL。这需要改分页逻辑,但改动量远小于换 UUID 主键。 - 排序问题:加密后的字符串排序和数字排序完全不同。如果前端需要按 ID 排序,后端解密后按数字排序即可,不影响功能。
总结建议
如果你不想动数据库结构,也不想在代码里到处替换 ID 类型,使用 Hashids 这种“编码/解码”方案是性价比最高的。
实施步骤:
- 引入 Hashids 库(几乎所有语言都有)。
- 写两个全局辅助函数:
encode_id($num)和decode_id($str)。 - 在 API 返回数据时,把所有的
id值过一遍encode_id。 - 在 API 接收参数时,把传入的
id过一遍decode_id。