• 请不要在回答技术问题时复制粘贴 AI 生成的内容
imherer
V2EX  ›  程序员

用户 ID 应该如何设计?

  •  
  •   imherer · Apr 9, 2019 · 10644 views
    This topic created in 2769 days ago, the information mentioned may be changed or developed.
    如果用数据库自增 ID 的话很容易被猜出来

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

    如何在保证很容易阅读的情况下,又保证不那么容易被猜出来呢?
    39 replies  •  2019-07-29 10:26:53 +08:00
    freedomshi
    freedomshi
    Apr 9, 2019
    1
    自定义格式
    yozi
    yozi
    Apr 9, 2019
    2
    来学习下,目前我们在使用 UUID,不知道有啥其他的方案吗
    honeycomb
    honeycomb
    Apr 9, 2019 via Android
    3
    参考 objectId,snowflake 这些同时具备自增+随机(或自定义)项的 ID ?
    maemual
    maemual
    Apr 9, 2019
    5
    发号器
    shakaraka
    shakaraka
    Apr 9, 2019
    6
    uuid
    imherer
    imherer
    OP
    Apr 9, 2019
    7
    @Lindp
    @wunonglin
    uuid 感觉有点太长了
    imherer
    imherer
    OP
    Apr 9, 2019
    8
    @honeycomb
    @maemual
    有稍微详细点的资料吗?谢谢!
    imherer
    imherer
    OP
    Apr 9, 2019
    9
    @cxh116 这个好像还可以。要是能是纯数字的就跟好了
    lihongjie0209
    lihongjie0209
    Apr 9, 2019
    10
    只要是数字都可以枚举

    204200231 和 1 的唯一区别就是枚举的难度而已。

    不想用自增 ID 可以用 时间戳
    cxh116
    cxh116
    Apr 9, 2019❤️2
    11
    @imherer 引用文档 " If you need your ids to consist of only numbers, check out Optimus. It's based on Knuth's integer hash method and produces obfuscated integer ids (and does it faster too). There are PHP and Go implementations. "
    imherer
    imherer
    OP
    Apr 9, 2019
    12
    @cxh116 嗯,看到了。刚才没细看文档
    x4storm
    x4storm
    Apr 9, 2019
    13
    时间戳加随机数
    beiping96
    beiping96
    Apr 9, 2019
    14
    Snowflake
    arjen
    arjen
    Apr 9, 2019 via Android
    15
    snowflake +1
    lps
    lps
    Apr 9, 2019
    16
    时间戳+随机数
    babedoll
    babedoll
    Apr 9, 2019
    17
    guid?

    好吧这个一点都不易读
    rogwan
    rogwan
    Apr 9, 2019 via Android
    18
    维护一个 ID 池,可以自己控制生成方式。
    klgd
    klgd
    Apr 9, 2019
    19
    容易被猜出来,然后呢?会有什么问题?
    shiww
    shiww
    Apr 9, 2019
    20
    @klgd 敏感信息
    huangdayu
    huangdayu
    Apr 9, 2019
    21
    将主键 id 加密
    huangdayu
    huangdayu
    Apr 9, 2019
    23
    hashids
    hansonwang99
    hansonwang99
    Apr 9, 2019
    24
    用 vesta 也行,https://www.codesheep.cn/2018/11/22/springbt-vesta/
    基本都是雪花算法
    loveour
    loveour
    Apr 9, 2019
    25
    为什么用户 id 是敏感信息,要用这个 id 做什么吗?有个简单做法,int 自增,另一半 int 随机一个数。之前我这用类似做法在用户 id 里填入一些自定义信息。这样,其中一部分很易读,但是想获得一个用户的完整 id 外部是做不到的。其实这个和拆分两个字段来确定一个用户差不多,和密码也差不多,只是合在了一起。再要么就随机数,哈希。
    klgd
    klgd
    Apr 9, 2019
    26
    @shiww #20 id 算什么敏感信息 我觉得只要能给到用户端看的,或者说能给第三个人看到的,都不算敏感,如果通过一个 id 就能获取用户的隐私信息,那么要么是原本就是设计如此,要么就是 bug
    v2ex 的“第 xx 号会员”应该也是用户的自增 id 吧
    jorneyr
    jorneyr
    Apr 9, 2019
    27
    我们使用 Snowflake
    feiyuanqiu
    feiyuanqiu
    Apr 9, 2019
    28
    @klgd #26 主要是防爬虫,一个用 ID 查询信息的接口,如果用自增 ID,爬虫一个循环就把数据爬走了,而复杂 ID 会让爬虫穷举的效率很低
    feiyuanqiu
    feiyuanqiu
    Apr 9, 2019
    29
    @klgd #26 另外,自增 ID 会暴露系统用户数等商业敏感信息
    ben1024
    ben1024
    Apr 9, 2019
    30
    hashids
    optimus
    zjsxwc
    zjsxwc
    Apr 9, 2019
    31
    所以最大的问题仅仅是设计接口时是否允许在 url 里暴露 id,而罪不在自增 id
    bwangel
    bwangel
    Apr 9, 2019❤️4
    32
    这个问题叫做 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
    feiyuanqiu
    Apr 9, 2019
    33
    @zjsxwc #31 接口不可能不暴露 ID,不在 url 上暴露也会在请求 body 里。

    自增 ID 还有一个问题是在分库分表系统中,会有 ID 重复的问题,所以包括 snowflake 在内的全局唯一 ID 方案,首要的目标就是为了支持分布式系统
    whypool
    whypool
    Apr 9, 2019
    34
    nanoid
    night98
    night98
    Apr 9, 2019
    35
    id 可自定义
    id 从 100000000000 和 2000000000 开始自增,类似 qq 号的思路。
    feiyuanqiu
    feiyuanqiu
    Apr 9, 2019
    36
    @bwangel #32 我们目前的方案是,主键用自增 ID,完全不参与业务逻辑,只用来当索引做排序;用 snowflake 生成一个业务 ID 唯一键,它是全局唯一的数据标识,参与业务。
    joesonw
    joesonw
    Apr 9, 2019
    37
    防爬的在网管层做一层 hashid 不就好了吗
    kayseen
    kayseen
    Jul 28, 2019
    38
    请问楼主最后选择了哪一种方法?
    imherer
    imherer
    OP
    Jul 29, 2019
    39
    @kayseen 尝试了几个,后来由于项目太赶了,就没在项目中尝试了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   676 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 140ms · UTC 21:06 · PVG 05:06 · LAX 13:06 · JFK 16:06
    ♥ Do have faith in what you're doing.