用户 ID 应该如何设计?

2019-04-09 10:37:05 +08:00
 imherer
如果用数据库自增 ID 的话很容易被猜出来

之前看腾讯的一些游戏用户 ID 都比较长,例如 204200231,看不出来有什么规律

如何在保证很容易阅读的情况下,又保证不那么容易被猜出来呢?
8750 次点击
所在节点    程序员
39 条回复
huangdayu
2019-04-09 16:00:20 +08:00
将主键 id 加密
hansonwang99
2019-04-09 16:02:01 +08:00
huangdayu
2019-04-09 16:02:23 +08:00
hashids
hansonwang99
2019-04-09 16:02:46 +08:00
用 vesta 也行,https://www.codesheep.cn/2018/11/22/springbt-vesta/
基本都是雪花算法
loveour
2019-04-09 16:06:12 +08:00
为什么用户 id 是敏感信息,要用这个 id 做什么吗?有个简单做法,int 自增,另一半 int 随机一个数。之前我这用类似做法在用户 id 里填入一些自定义信息。这样,其中一部分很易读,但是想获得一个用户的完整 id 外部是做不到的。其实这个和拆分两个字段来确定一个用户差不多,和密码也差不多,只是合在了一起。再要么就随机数,哈希。
klgd
2019-04-09 16:16:32 +08:00
@shiww #20 id 算什么敏感信息 我觉得只要能给到用户端看的,或者说能给第三个人看到的,都不算敏感,如果通过一个 id 就能获取用户的隐私信息,那么要么是原本就是设计如此,要么就是 bug
v2ex 的“第 xx 号会员”应该也是用户的自增 id 吧
jorneyr
2019-04-09 16:17:18 +08:00
我们使用 Snowflake
feiyuanqiu
2019-04-09 16:26:13 +08:00
@klgd #26 主要是防爬虫,一个用 ID 查询信息的接口,如果用自增 ID,爬虫一个循环就把数据爬走了,而复杂 ID 会让爬虫穷举的效率很低
feiyuanqiu
2019-04-09 16:28:06 +08:00
@klgd #26 另外,自增 ID 会暴露系统用户数等商业敏感信息
ben1024
2019-04-09 16:35:29 +08:00
hashids
optimus
zjsxwc
2019-04-09 16:43:30 +08:00
所以最大的问题仅仅是设计接口时是否允许在 url 里暴露 id,而罪不在自增 id
bwangel
2019-04-09 16:45:44 +08:00
这个问题叫做 ID 混淆,

http://python.jobbole.com/85534/ 这篇文章介绍了一种混淆 ID 的方法。这个不要再数据库层做,数据库中的 ID 一定要使用自增 ID,要不然会影响索引。这个需要在视图层做,Python web 框架可以搭配 WSGI 中间件一起实现。

如果使用 Django 搭建 API 服务,可以这么实现

1. 为 ID 新建一种类型,IntID
2. model 层返回的 id 字段都是 intID 类型
3. 视图层不要返回 HTTP Response,返回字典。
4. (关键)写一个 wsgi 中间件,拦截响应,如果响应是字典,则使用 JSON 格式化,并返回一个 JSONHTTP Response。JSON 格式化的时候需要自己写 encoder,判断如果是 IntID 类型,使用上述的混淆方法格式化,这样返回的整数是被混淆的字符串了
5. (关键)写一个 WSGI 中间件,拦截请求,将 POST 和 GET 数据都封装成字典存放到 request 中。然后每个请求的数据都要使用类似于 Form 的东西来处理一遍。Form 中自己可以实现一个 field,叫做 IntID field,就是执行反混淆的任务,将字符串的 ID 转换成数字 ID。
feiyuanqiu
2019-04-09 16:54:40 +08:00
@zjsxwc #31 接口不可能不暴露 ID,不在 url 上暴露也会在请求 body 里。

自增 ID 还有一个问题是在分库分表系统中,会有 ID 重复的问题,所以包括 snowflake 在内的全局唯一 ID 方案,首要的目标就是为了支持分布式系统
whypool
2019-04-09 16:56:16 +08:00
nanoid
night98
2019-04-09 16:57:33 +08:00
id 可自定义
id 从 100000000000 和 2000000000 开始自增,类似 qq 号的思路。
feiyuanqiu
2019-04-09 17:00:22 +08:00
@bwangel #32 我们目前的方案是,主键用自增 ID,完全不参与业务逻辑,只用来当索引做排序;用 snowflake 生成一个业务 ID 唯一键,它是全局唯一的数据标识,参与业务。
joesonw
2019-04-09 18:38:46 +08:00
防爬的在网管层做一层 hashid 不就好了吗
kayseen
2019-07-28 22:50:13 +08:00
请问楼主最后选择了哪一种方法?
imherer
2019-07-29 10:26:53 +08:00
@kayseen 尝试了几个,后来由于项目太赶了,就没在项目中尝试了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/553247

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX