V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
imherer
V2EX  ›  程序员

用户 ID 应该如何设计?

  •  
  •   imherer · 2019-04-09 10:37:05 +08:00 · 8677 次点击
    这是一个创建于 1815 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如果用数据库自增 ID 的话很容易被猜出来

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

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

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

    不想用自增 ID 可以用 时间戳
    cxh116
        11
    cxh116  
       2019-04-09 12:01:29 +08:00   ❤️ 2
    @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
        12
    imherer  
    OP
       2019-04-09 12:03:20 +08:00
    @cxh116 嗯,看到了。刚才没细看文档
    x4storm
        13
    x4storm  
       2019-04-09 12:41:45 +08:00
    时间戳加随机数
    beiping96
        14
    beiping96  
       2019-04-09 14:07:40 +08:00
    Snowflake
    arjen
        15
    arjen  
       2019-04-09 14:16:23 +08:00 via Android
    snowflake +1
    lps
        16
    lps  
       2019-04-09 14:48:52 +08:00
    时间戳+随机数
    babedoll
        17
    babedoll  
       2019-04-09 14:51:37 +08:00
    guid?

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

    自增 ID 还有一个问题是在分库分表系统中,会有 ID 重复的问题,所以包括 snowflake 在内的全局唯一 ID 方案,首要的目标就是为了支持分布式系统
    whypool
        34
    whypool  
       2019-04-09 16:56:16 +08:00
    nanoid
    night98
        35
    night98  
       2019-04-09 16:57:33 +08:00
    id 可自定义
    id 从 100000000000 和 2000000000 开始自增,类似 qq 号的思路。
    feiyuanqiu
        36
    feiyuanqiu  
       2019-04-09 17:00:22 +08:00
    @bwangel #32 我们目前的方案是,主键用自增 ID,完全不参与业务逻辑,只用来当索引做排序;用 snowflake 生成一个业务 ID 唯一键,它是全局唯一的数据标识,参与业务。
    joesonw
        37
    joesonw  
       2019-04-09 18:38:46 +08:00
    防爬的在网管层做一层 hashid 不就好了吗
    kayseen
        38
    kayseen  
       2019-07-28 22:50:13 +08:00
    请问楼主最后选择了哪一种方法?
    imherer
        39
    imherer  
    OP
       2019-07-29 10:26:53 +08:00
    @kayseen 尝试了几个,后来由于项目太赶了,就没在项目中尝试了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3191 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 14:26 · PVG 22:26 · LAX 07:26 · JFK 10:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.