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

应不应该把主键 id 暴露在 url 上?

  •  1
     
  •   felix9ia · 19 小时 30 分钟前 · 4217 次点击

    想请教一下大家是怎么做的?

    比如访问一个电商网站的店铺页面的 url:

    方式 1:使用自增的主键 id xxx/shop/123

    方式 2:使用雪花主键 id 或者 guid

    xxx/shop/1881238297653633026

    xxx/shop/85d93ea0-3d43-48c5-99ec-e11f54655228

    方式 3: 使用业务编号

    xxx/shop/st_003

    方式 4:

    用 sqids 把所有的实体主键 id(private_id) 在转换 VO 时加盐转换成 (public_id) 返回给前端

    相关讨论: https://www.reddit.com/r/csharp/comments/rg7xob/is_it_bad_to_expose_primary_key_to_the_user_if/

    55 条回复    2025-01-22 09:03:00 +08:00
    Rickkkkkkk
        1
    Rickkkkkkk  
       19 小时 27 分钟前
    不是自增的就行
    javalaw2010
        2
    javalaw2010  
       19 小时 25 分钟前
    在绝大部分场景下,我推崇方案 1 ,如果有产品端/安全端的特殊需求,我会考虑方案 3 ,只有再极少数场景下,比如日志追踪等,我会考虑 2
    javalaw2010
        3
    javalaw2010  
       19 小时 24 分钟前
    @javalaw2010 原贴编辑过了吗?我这里的方案 3 指的是加盐,方案 2 指的是 uuid
    laobobo
        4
    laobobo  
       19 小时 22 分钟前
    我(前端)做过的功能,后端给几乎都是用的自增 ID ,极少数场景才会用 2 ,其他目前没遇到
    felix9ia
        5
    felix9ia  
    OP
       19 小时 22 分钟前
    @javalaw2010 是的,不好意思,我刚刚改了一下。

    其实方案 1 的自增有明显的缺陷,不应该被推荐把? 用 sqids 加盐我觉得也是少数场景,比如用户主页这种。
    CHTuring
        6
    CHTuring  
       19 小时 20 分钟前
    2 就够用了,还是像楼上说的,只要不是自增就行了。
    felix9ia
        7
    felix9ia  
    OP
       19 小时 18 分钟前
    @laobobo 其实,我的这个问题有场景限制,就是在客户端,而不是后台管理页面。

    如果是后台管理,我觉得暴露自增 id 没有关系。
    felix9ia
        8
    felix9ia  
    OP
       19 小时 16 分钟前
    方案 4 有一个好处就是,定期更换盐,可以让链接失效,当然让链接失效有好处也有坏处
    laobobo
        9
    laobobo  
       19 小时 15 分钟前
    @felix9ia 嗯,如果是用户端,个人感觉还是不要暴露自增 id ,总感觉不安全
    javalaw2010
        10
    javalaw2010  
       19 小时 13 分钟前
    自增 id 除了暴露数据量之外,其他我也没觉得会有啥缺陷,而“暴露数据量”这件事也只有少数场景下才值得被关注,这些场景下就需要具体问题具体分析,比如订单相关场景,其实订单号比 ID 更像事实上的主键(我个人喜欢在绝大多数场景下都保留自增 ID ),业务上基本使用订单号而非主键。
    iyiluo
        11
    iyiluo  
       19 小时 11 分钟前
    肯定不能用自增,首先安全那关就过不去,可以被黑产猜测到数据,遇到爬虫,直接把你整个业务的数据都扒下来。用 md5, uuid, 雪花都行
    anonydmer
        12
    anonydmer  
       18 小时 52 分钟前
    目前项目都用 ULID
    musi
        13
    musi  
       18 小时 49 分钟前
    暴露自增 id 有什么问题吗?
    我没见 v2 有什么安全性问题啊
    zpfhbyx
        14
    zpfhbyx  
       18 小时 44 分钟前
    数字没问题啊, 只要不是自增就行 足够大 轮训不全的.
    felix9ia
        15
    felix9ia  
    OP
       18 小时 44 分钟前
    @musi V2EX 用的是自增 id ?

    https://www.v2ex.com/t/1106781
    musi
        16
    musi  
       18 小时 42 分钟前
    @felix9ia t 后面的不就是帖子 id 么,你加一减一不也能看到其他帖子么
    mxT52CRuqR6o5
        17
    mxT52CRuqR6o5  
       18 小时 41 分钟前
    也可以用对称加密算法加个密,不知道密钥的话也破解不了
    felix9ia
        18
    felix9ia  
    OP
       18 小时 41 分钟前
    @musi 卧槽,还真是
    kingcanfish
        19
    kingcanfish  
       18 小时 33 分钟前
    其实 暴露在 url 上和暴露在接口 json 中没啥区别,不自增就行
    飞书一样暴露出来的
    hertzry
        20
    hertzry  
       18 小时 30 分钟前 via iPhone
    京东这一串应该也是自增。
    https://item.jd.com/product/7323507.html
    DonaldY
        21
    DonaldY  
       18 小时 27 分钟前
    @musi
    @felix9ia
    直接用自增 id ,方便爬虫穷举。

    有权限的数据页面不应该用自增 id 在 url 上
    dylanqqt
        22
    dylanqqt  
       18 小时 26 分钟前
    我想问一下自增的有什么风险?
    jaylee4869
        23
    jaylee4869  
       18 小时 15 分钟前
    @dylanqqt 没有做好数据权限控制会导致数据泄露的越权操作。
    BeijingBaby
        24
    BeijingBaby  
       18 小时 13 分钟前
    安全性上讲,无所谓自增,有人说方便爬取,想多了。你随机 id 要爬取你也能爬到啊,只要数据是公开的,和自增和随机的没任何区别。
    有时候更多的是考虑暴漏业务数据量,以及分布式的时候,才抛弃自增 id 。
    zt5b79527
        25
    zt5b79527  
       18 小时 11 分钟前
    @dylanqqt 简单来说,别人能猜到你的数据量。比如说订单号自增,竞争对手就能知道你的订单量。比如之前 b 站的 bv 号,最初好像也是自增的,竞争对手就能知道平台的投稿量,后来就换成随机的了(应该不全是这个原因,但是肯定有这方面的考量)
    esee
        26
    esee  
       18 小时 8 分钟前
    主键用的自增 ID, 后端接口查询的时候,sql 语句对 id 加密查询出来,我是这样做的.
    musi
        27
    musi  
       18 小时 8 分钟前
    @DonaldY #21 简单的数字我也可以穷举吧
    zjsxwc
        28
    zjsxwc  
       18 小时 7 分钟前
    自增 id 方便调试和 dba 维护,大部分时候自增 id 就够用了,
    我只在 serverless 系统上看到用 uuid 的
    wangtian2020
        29
    wangtian2020  
       18 小时 7 分钟前
    可以暴露,暴露在 url 中与暴露在请求体里有什么区别。
    问题是不要使用自增 id 暴露网站后台的规模!
    订单 id 自增暴露每日订单数量,商品 id 自增暴露订单数量
    dylanqqt
        30
    dylanqqt  
       18 小时 4 分钟前
    @zt5b79527 这种算不上什么,自增 id 可以从 1 开始自增,也可以从 10000000 开始自增,别人咋看?至于小公司根本不在乎这个 id 暴露。
    chendy
        31
    chendy  
       18 小时 4 分钟前   ❤️ 1
    暴露 id 本身没啥问题
    暴露 id + 自增 id 可能导致的问题:
    1. 对外的系统,纯自增 id 可以推算出数据增长量,暴露业务情况
    2. 如果权限做的不好,用户或者爬虫可以通过 id 遍历全部数据
    处理方式也很简单:
    1. 用一些操作对数据进行加密/编码
    2. 完善权限,完善风控
    yelog
        32
    yelog  
       18 小时 1 分钟前
    @dylanqqt 容易被暴力攻击越权漏洞, 假如微博的私信列表有越权漏洞

    你在进入微博的私信页面, 发现获取私信列表的接口是 weibo.com/p_message/16645, 然后你把最后的数字(id) 改为 1, 发现获取到管理员 admin 的私信列表了哈哈哈, 然后依次加 1, 可以非常快把微博的所有用户的私信列表全部下载下来

    如果不是自增的, 比如 UUID, 尽管知道这个接口越权漏洞, 但是鉴于 UUID 的随机性和位数, 用户隐私泄漏的风险就非常小
    TimePPT
        33
    TimePPT  
       17 小时 57 分钟前
    @chendy 完全同意,其实主要问题就是推断业务增长情况,和遍历爬虫(一个冷知识:QQ 邮箱的数字 @qq.com 也有类似问题所以一开始入信反垃圾策略就很严格),其他没啥大问题。

    我新项目一般数据库用 PostgreSQL ,唯一 id 使用 uuidv7 ,传给前端 url 外显时候使用 url safe 的 base64 显示了,除了丑点没啥其他副作用。
    cxxlxx
        34
    cxxlxx  
       17 小时 57 分钟前
    liuidetmks
        35
    liuidetmks  
       17 小时 56 分钟前
    @dylanqqt 从 1w 开始,并不能起到很大作用,人家只有作差分就能获取你某段时间内业务规模了
    自增 id 也有其他风险,
    比如某个接口配置失误,通过订单号直接查询数据,还是比较危险的
    importmeta
        36
    importmeta  
       17 小时 54 分钟前
    里面逻辑再拿用户 id,加一层保险
    SoyaDokio
        37
    SoyaDokio  
       17 小时 54 分钟前
    根据 RESTful 语义原则,当然是把 ID 放在 URL 里更好,但仅限于 UUID 或其他类似主键。
    自增主键的话,建议还是隐藏起来,以免用户可以轻松批量暴库。
    default996
        38
    default996  
       17 小时 45 分钟前
    通常建表时我会创建 id,created_at, updated_at
    然后一般情况下我会使用自增 ID;
    特殊情况下,我会使用 id+created_at ,只有两个都匹配到才能查询到记录
    Reficul
        39
    Reficul  
       17 小时 18 分钟前
    自增 ID 可能会暴露你们业务一天有多少数据,比如订单量之类的。之前我们懒惰 fix 这个问题的方法是随机跳过部分数字来给数据投毒。
    voy
        40
    voy  
       16 小时 59 分钟前
    hackernews is self increased. done.
    forty
        41
    forty  
       16 小时 58 分钟前   ❤️ 1
    有时候杀鸡用不上牛刀。

    其实还有 1 种简单方案,叫 hashid, 几十种语言的实现都有, github 可用搜到,可以在纯数字和"hashid"之间互相转换,既不直接暴露主键数字 id 给前端,无法被人直接遍历,同时也不增加后端复杂度。
    Hashids 改名叫 Sqids 了. https://sqids.org/

    原来 @cxxlxx 已经提出来了,刚开始没注意到。
    thinkershare
        42
    thinkershare  
       16 小时 55 分钟前
    自增的也无所谓,需要安全的地方,需要其它权限鉴定逻辑。
    ntedshen
        43
    ntedshen  
       16 小时 52 分钟前
    如果你用 innodb 的话,可以把 update 全部改成 insert ignore on duplate update ,你就能得到一个超音速自增的主键(狗头
    Zcyisabigman
        44
    Zcyisabigman  
       16 小时 51 分钟前
    用自增的一些缺点:
    1 ,暴露业务数据规模,著名的瑞幸咖啡那件事就是被人蹲点捡小票,通过 ID 推算真实业务量
    2 ,方便爬虫写脚本抓数据
    3 ,存在缓存击穿问题???
    chairuosen
        45
    chairuosen  
       16 小时 51 分钟前
    要看业务是不是数据都公开,京东的商品,论坛的帖子,这种无所谓。资源要做隔离的就需要考虑隐藏了
    xuelu520
        46
    xuelu520  
       16 小时 44 分钟前
    暴露有什么影响吗?
    有些 ID 暴露也无所谓啊,就例如这个帖子的 ID 不就在 url 上
    涉及到隐私和安全的可以考虑加密或雪花或其他方案加密。
    正常用的无所谓的,做好暴露后问题的处理就行。
    nekochyan
        47
    nekochyan  
       16 小时 24 分钟前
    我们有个项目是直接用 ID 异或一个较大的数给前端就行了,然后再异或回来
    zt5b79527
        48
    zt5b79527  
       16 小时 5 分钟前
    @dylanqqt #30 单单业务规模这一点,确实对小公司可能不算什么,那大公司呢?如果是年营收上百亿,竞争对手虎视眈眈的上市公司呢?对于大公司来说,安全才是第一位的。竞争对手可能已经通过各种渠道收集了你各种各样的信息,再加上这一点交叉验证,底裤都给你扒出来。
    ospider
        49
    ospider  
       16 小时 1 分钟前
    snowflake id 就足够了,别的纯属想太多
    yh7gdiaYW
        50
    yh7gdiaYW  
       15 小时 49 分钟前
    看完这贴我就把 v 站的第 1,10,100,1000,10000,100000,1000000 贴看了一遍
    对很多业务来说这么轻易的能跳转是不可接受的
    lcy630409
        51
    lcy630409  
       15 小时 23 分钟前
    自增 id 然后商户可以 缴纳 30 元 自定义一个“靓号”
    xuanbg
        52
    xuanbg  
       15 小时 19 分钟前
    不连续就行了
    spike0100
        53
    spike0100  
       14 小时 56 分钟前 via iPhone
    可以考虑 hashids 对主键进行映射
    dylanqqt
        54
    dylanqqt  
       55 分钟前
    @zt5b79527 https://ic-item.jd.com/100143612769.html 京东算不算大公司?只能说这并不算什么大不了的事情。
    dylanqqt
        55
    dylanqqt  
       52 分钟前
    @liuidetmks 危险是因为接口配置失误了危险,并不是自增 id 危险。就像支付宝这次打折 20%一样,并不是开发这个打折 20%的功能很危险,是因为配置错误了很危险。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5646 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 01:55 · PVG 09:55 · LAX 17:55 · JFK 20:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.