这是一个专门讨论 idea 的地方。

每个人的时间,资源是有限的,有的时候你或许能够想到很多 idea,但是由于现实的限制,却并不是所有的 idea 都能够成为现实。

那这个时候,不妨可以把那些 idea 分享出来,启发别人。
est

想到一个自增 id 但是同时防止遍历的办法

  •  2
     
  •   est · Nov 12, 2015 · 16773 views
    This topic created in 4009 days ago, the information mentioned may be changed or developed.
    比如会员, uid 从 1 开始,那么一些人就可以从 1 开始爬虫。。。

    于是我在脑洞一些办法防止这个事。有的用uuid,甚至hash,感觉都不是很友好。在保持id自增的前提下,我想了一些办法:

    第一个手段当然是限频率和屏蔽手段。。。

    第二个手段,就是把自增 id 弄成稀疏的。 比如统统跳过 id 个位数为 7 的。。那么如果有人故意访问 uid=7, uid=17, uid=27 等等,就直接判定为爬虫,封锁之。

    当然,判断个位数,这个很容易被发现规律猜到。

    那么,有没有比较好的算法,让人猜不到这个 “间隙” id 的规律,但是服务器又非常容易判断为不可用 id 呢?
    85 replies  •  2015-11-20 10:31:59 +08:00
    pubby
    pubby
    Nov 12, 2015
    1
    偶尔我用 /user/{uid}-{md5(uid+key)} 的形式防止遍历
    est
    est
    OP
    Nov 12, 2015
    2
    @pubby 这个也太复杂了。。。 id 太长。。
    wy315700
    wy315700
    Nov 12, 2015
    3
    short_uuid
    undeflife
    undeflife
    Nov 12, 2015
    4
    不需要算法 id 随便什么规律都好 没规律也行
    fail2ban 解析 access.log 多次符合规则的 404 ban 掉就行了
    pubby
    pubby
    Nov 12, 2015
    5
    @est 嗯,所以偶尔用用。
    ts
    ts
    Nov 12, 2015
    6
    @est 大神你还经常在哪些站里出没或者潜水 除了 v2
    est
    est
    OP
    Nov 12, 2015
    7
    @undeflife 这个有一个问题就是别人可以新注册一个用户,看 uid 可以大致判断出你总用户数是多少。。。
    @wy315700 也可行。但是无序了。 id 自增感觉要好点。。
    xujif
    xujif
    Nov 12, 2015
    8
    弄几个魔术 id ,访问就 ban
    cyr1l
    cyr1l
    Nov 12, 2015❤️1
    9
    比如判断是否是质数或者是否能被某个质数(比如 17 ) 整除?
    akira
    akira
    Nov 12, 2015
    10
    自增的 id 只对内部使用,对外是一个 uuid 或者和 id 无表面关系的字符串
    lanlanlan
    lanlanlan
    Nov 12, 2015
    11
    只要爬虫 IP 资源够 都是浮云嘛→_→
    est
    est
    OP
    Nov 12, 2015
    12
    @wy315700 而且如果 mysql 里用的话,还有可能冲突。。虽然很小概率。但是为了防止冲突还得加个唯一索引。这是要让人纠结死。。。而如果自增的话,直接根据上一个 id ,按照某一个算法,跳过一些 id ,就可以得到下一个 id 了。。。现在就是在想有没有这个比较好的算法。不容易猜出来,服务器计算和判断速度也比较快的。
    est
    est
    OP
    Nov 12, 2015
    13
    @lanlanlan 如果加上运营商判断, ip 没那么好找哦。比如只允许 ADSL 的 IP 段访问,代理 ip 绝大多数是机房 ip 段。很容易判断出来。我见过很多国外论坛都只允许 comcast verizon at&t 之类的民用宽带 ip 访问。我换了 n 个代理,但是因为出口都是机房,都被判断出来了。
    est
    est
    OP
    Nov 12, 2015
    14
    @xujif 我也是这样想的,但是从代码维护的角度来说,每人工增加一个 magic id 就要改代码,部署流程,或者改 config ,感觉略蛋痛。
    est
    est
    OP
    Nov 12, 2015
    15
    @ts reddit hacker news. 我现在也想找别的地方混。
    est
    est
    OP
    Nov 12, 2015
    16
    @cyr1l 差不多是这个方向。。。不知道大家有没有灵光一现更加 NB 的。。
    Elethom
    Elethom
    Nov 12, 2015 via iPhone
    17
    那自增就沒有意義了。還不如 hash 。
    zhujinliang
    zhujinliang
    Nov 12, 2015
    18
    之前有个类似的需求,当时的做法很 2b
    把 id 以十进制表示,然后每位随机做一个的对照表,然后再拼起来
    RitianZhao1988
    RitianZhao1988
    Nov 12, 2015
    19
    内部一张表,外部一张表
    外部增加时有几率增加 rand 个魔术 id ,然后在内部表里再写一份没有 magic id 的怎么样?
    undeflife
    undeflife
    Nov 12, 2015
    20
    @est 你的"间隙" id 同样不能解决这个问题
    如果 /users/xxxx 这样一个 url 并不存在分享的需求的话 无所谓友好不友好.
    如果存在分享的需求的话 /users/username 这样不是更好吗
    所以我认为完全可以从设计上弱化 uid 在用户这的存在
    wy315700
    wy315700
    Nov 12, 2015❤️1
    21
    @est short_uuid 是 MySQL 的一个 64 位增长型 ID 啊,就是满足你的要求的,
    18000rpm
    18000rpm
    Nov 12, 2015
    22
    跟着思路走只能想到多挖几个坑 233
    一个一位数的坑
    两个两位数的坑
    三个三位数的坑
    能整除的都不能踩,不知道这个在没遍历前还好不好猜规律
    lwbjing
    lwbjing
    Nov 12, 2015
    23
    mongodb _id
    oott123
    oott123
    Nov 12, 2015❤️1
    24
    lincanbin
    lincanbin
    Nov 12, 2015
    25
    用 GUID+截断的时间戳作为主键,可以获得更高的插入效率,同时也可以一定程度防止爬虫。
    muzuiget
    muzuiget
    Nov 12, 2015
    26
    自增 id 只在服务器器使用,对外就 hash 不就行了么, hash 同表也是唯一,允许所以?不让客户端通过 id 访问到资源。
    imn1
    imn1
    Nov 12, 2015
    27
    虽然会增加我将来爬东西的难度,但还是要说一句话:
    外显有序 id 是低智商

    说个故事:
    上世纪末,要抓日本某站点一批数据,当时只知道 max(id)>=17000 ,步长 1 自增
    还不会写爬虫,于是开网络蚂蚁批量,直接下
    大约抓了 5000 条左右,那站点停了几小时,然后页面浏览器访问顶部出现了“巡回禁止”的横条,哈哈
    然后发现大约下 1000 条左右后面就会全部 404
    老子 proxy 多,当年还没有 qiang 的概念, ssl proxy 都是稀有物,但 http proxy 还是不少,因为原生网路就不畅,非人为原因……
    然后就每 800 条换一个 proxy ,爬完(换了多个确认是真的没有数据而不是 404 ),总数 26000+条
    这是当年不为爬 qiang 而使用梯子的典型例子
    凭这 2w 条信息,虽然没有全部发布,并且是重新组织和翻译,在小圈子也有点名气
    但也属盗版了,后来还是怕担责(即使日本追究不到我这来),撤了,自此之后虽然爬数据,但再也没批量公开发布了
    反正从那时开始我就禁止后台程序员使用外显有序 id 了

    @akira 说的是对的,其实不要想什么算法,因为读取的次数比写入多得多,在写入时产生一个唯一用于外显的 uid 则可,读取时用算法判定会严重增加机器负担
    est
    est
    OP
    Nov 12, 2015❤️1
    28
    @undeflife 用户 id 只是举个例子。有很多时候会用到 id 的。
    @imn1 其实还有一招。就是不封,也不返回任何错误,直接随机产生垃圾内容。。。让你区分不出来内容是否真实的。。。我抓 bing 就遇到这问题了。。。。。。。嗯。。。。。。。。

    即便是外显 uid ,也是需要防止爬虫呀。。。这个时候除非做 hash ,否则依然也是有问题的。
    est
    est
    OP
    Nov 12, 2015
    29
    @wy315700

    仔细看了下

    The UUID_SHORT() return value is constructed this way:

    (server_id & 255) << 56
    + (server_startup_time_in_seconds << 24)
    + incremented_variable++;

    感觉也算一个不明显的自增 id 的思路吧。。。。
    est
    est
    OP
    Nov 12, 2015
    30
    @oott123 好东西。不过 ruby 有个更好的,基于 Perfect hash function 的 https://github.com/namick/obfuscate_id
    imn1
    imn1
    Nov 12, 2015
    31
    @est
    我没说不防啊,只是你别只穿着内衣上地铁,然后举个牌子“我可以骚,你不可扰”,这算什么?
    livelazily
    livelazily
    Nov 12, 2015
    32
    跳过所有质数
    oott123
    oott123
    Nov 12, 2015
    33
    @est 恕我愚昧,没发现哪里“更好”了。
    lerry
    lerry
    Nov 12, 2015
    34
    twor2
    twor2
    Nov 12, 2015
    35
    uuid 只是视觉上的长,其实还好,网址都是点进去的,就算是 1234 ,也不会有人敲进去吧
    liboyue
    liboyue
    Nov 12, 2015
    36
    用一个表呗。把顺序的内部 ID 映射到随机 ID 上,多一次查表的操作
    XiaoxiaoPu
    XiaoxiaoPu
    Nov 12, 2015
    37
    把自增 ID 用 RSA 加密(或其他加密算法),加密后的结果给用户,用户传过来的 ID 解密,不知道是否可行
    est
    est
    OP
    Nov 12, 2015
    38
    @livelazily 2333 好办法!
    ts
    ts
    Nov 12, 2015
    39
    @est 有中文类别的坛子或者网站吗 求大神的 bookmark .....
    millken
    millken
    Nov 12, 2015❤️2
    40
    est
    est
    OP
    Nov 12, 2015
    41
    @ts 网址我都背熟了。 newsmth.net/mainpage.html 纯手打。
    wingoo
    wingoo
    Nov 12, 2015
    42
    base62
    映射规则自己指定下
    hooopo
    hooopo
    Nov 12, 2015
    43
    内部设置一个私有函数产生黑洞 ID...
    ooh
    ooh
    Nov 12, 2015
    44
    没有任何实际意义
    windows98
    windows98
    Nov 12, 2015❤️1
    45
    看帖子的同时,瞟了一眼这个帖子的 url...
    ibireme
    ibireme
    Nov 12, 2015
    46
    用 MongoDB 的 ID 生成办法就不错啊~
    est
    est
    OP
    Nov 12, 2015
    47
    @hooopo 就是这个意思。。。那么,大家有没有什么好的私有函数建议呢。要无状态,速度快,很难逆向出的。。。这个帖子 /t/233004 被 @binux 弄一个一元四次方程就给破了。。。。。。。。。。
    dong3580
    dong3580
    Nov 12, 2015
    48
    @est
    没用,我不信你作出站无目录列表,

    @XiaoxiaoPu
    这样变化的 id ,你让搜索引擎怎么收录?
    est
    est
    OP
    Nov 12, 2015
    49
    @dong3580 没看懂。什么没用?
    Felldeadbird
    Felldeadbird
    Nov 12, 2015
    50
    如果是闭源的话,直接 参数+自增 ID+参数。 混淆进去就行了。
    如: order_id =1 ;那么访问的 URL 地址为:
    /xxx.io?order=6544678198786782 拆分为三部分: 6544678 、 1 、 98786782 。
    fork3rt
    fork3rt
    Nov 12, 2015
    51
    好无聊的方法。。。
    zdhxiong
    zdhxiong
    Nov 12, 2015
    52
    @est 不管你的网址弄得多复杂,一个 wget 命令都能把你的整个站镜像下来。
    xierch
    xierch
    Nov 12, 2015
    53
    next_id = hmac(last_id, key) % MAX_GAP + 1
    xierch
    xierch
    Nov 12, 2015
    54
    哦,不是 =,是 +=
    xierch
    xierch
    Nov 12, 2015
    55
    next_id = last_id + 1 + hmac(last_id, key) % MAX_GAP
    est
    est
    OP
    Nov 12, 2015
    56
    @zdhxiong 你再想想呢?比如我 margin-left: -10000px 一个 div 里弄一个陷阱链接,你访问就直接给你永久返回垃圾数据。镜像下来然后呢?
    huobazi
    huobazi
    Nov 12, 2015
    57
    snowflake
    est
    est
    OP
    Nov 12, 2015
    58
    iambic
    iambic
    Nov 12, 2015
    59
    感觉是不是就是一个 integer hashing 问题啊

    这个链接 https://gist.github.com/badboy/6267743 应该有用。另外 redis 源码里, dict.c 用的 Thomas Wang 的 hashing function 应该也可以参考下
    clino
    clino
    Nov 12, 2015
    60
    取当前时间
    typcn
    typcn
    Nov 12, 2015
    61
    @est 搜索引擎蜘蛛也会这样的。。
    est
    est
    OP
    Nov 12, 2015
    62
    @iambic 这也是个好思路。
    est
    est
    OP
    Nov 12, 2015
    63
    @typcn 增加一行 UA+IP 地址段判断,不拉黑就是了。
    hooopo
    hooopo
    Nov 12, 2015
    64
    @est 无规律的随机点就可以,加一个 hole 表...里面随机填一些 id 就好吧
    est
    est
    OP
    Nov 12, 2015
    65
    @hooopo 感觉通过算法算出来的好好玩一点。。
    jsq2627
    jsq2627
    PRO
    Nov 12, 2015
    66
    UUID/GUID 当然是最好的。只不过长的比较丑,对用户不友好。不过还是可以避免,我们最近在做的一个系统,用户注册后就必须得输入一个五位代码做 URL 定位部分。
    FrankFang128
    FrankFang128
    Nov 12, 2015
    67
    ban 有什么用,很快就发现你的规律了。
    displayabc
    displayabc
    Nov 12, 2015
    68
    用进制转换啊, 10 进制转换成 36 进制, 10 数字加 26 个字母,把顺序打乱
    xierch
    xierch
    Nov 12, 2015
    69
    不如 ID 还是按顺序自增,但是提供给用户的时候,在末尾加一位数用作校验?
    效果应该类似于,每两个 ID 之间平均间隔 10 个黑洞
    校验值可以用任意算法加密 ID ,然后 mod 10 得到..

    推广一下,可以用 id * N + (encrypt(id) % N) 得到带校验码的 id_v
    服务器收到 id_v 以后,用 id_v / N 得到原 ID ,
    然后用 id_v % N == encrypt(id, key) % N 判断是否正确。
    ( N >= 2 ,越大掺的洞越多(
    dallaslu
    dallaslu
    Nov 12, 2015
    70
    1. 使用自增 ID ,记为 A ;
    2. 生成 UUID ,去掉前面的 0 ,再取前 X 位按 16 进制转为 10 进制的值,记为 B ;
    3. 计算 X 位 16 进制数字的 10 进制值的数字个数(如 4 位 16 进制数字 FFFF 10 进制值为 65535 ,数字个数为 5 ),记为 C ;
    4. 在 B 的前面补 0 ,以使长度等于 C ,将其记为 D ;
    5. 把 A 和 D 拼接起来,用做外显 ID 。

    比如设 X 为 4 , A 为 235554 , UUID 为 3FE4C8B33C ...,则:

    B = 0x3FE4 = 16356 ;
    C = 5 ;
    D = 16356 ;
    ID = 23555416356

    遇到 404 就可以判为爬虫了。话又说回来,自增 ID 后面拼上定长的随机数不就好了么!
    dallaslu
    dallaslu
    Nov 12, 2015
    71
    当然了,如果还有校验的需求,可以用 md5(id+salt) 来代替 UUID ,参与 12345 运算……
    hansnow
    hansnow
    Nov 12, 2015
    72
    @est 其实我想说,你是唯一一个我在 D 版和 v2 同时看到的活跃 id
    ctftemp
    ctftemp
    Nov 12, 2015 via Android
    73
    id 加盐 hash 一下,拿这个 hash 值作为判断依据就比较难预测了吧?
    pepsin
    pepsin
    Nov 12, 2015
    74
    @hansnow 你可能看漏我了
    hansnow
    hansnow
    Nov 12, 2015
    75
    @pepsin 哈哈哈,看你头像就想起来了
    Hipponensis
    Hipponensis
    Nov 12, 2015
    76
    LS 许多思路学习了,但总觉得防遍历有点舍本逐末,不如 ID 还是按顺序自增,然后下陷阱,某些 id 对应的页面用户无法访问,让爬虫进去,然后封禁对应 ip 。以上爬虫新手瞎想的。
    varrily
    varrily
    Nov 12, 2015
    77
    我在用 base58(uuid) 长度 22 位左右。比直接 uuid 短不少。
    msg7086
    msg7086
    Nov 12, 2015
    78
    @haython http://ra.gg/!iMD4o 以前还做过类似的东西其实。

    @xierch 其实信用卡、身份证,都是基于这个机制。
    abscon
    abscon
    Nov 13, 2015 via iPhone
    79
    @twor2 我就敲网址。有时候这是最方便的
    holyghost
    holyghost
    Nov 13, 2015 via iPhone❤️1
    80
    有开源的 hashids 不用。。。
    xiaogui
    xiaogui
    Nov 13, 2015
    81
    @holyghost hashids 看着好棒,哈哈。
    xiaogui
    xiaogui
    Nov 13, 2015
    82
    不过非连续 ID 并不能完全阻止被爬虫。
    est
    est
    OP
    Nov 13, 2015
    83
    @xiaogui 为什么?
    xiaogui
    xiaogui
    Nov 13, 2015
    84
    @est 只要你把内容显示给用户,就不能保证爬虫不会抓取,只不过可能会让爬虫麻烦点而已。
    un
    un
    Nov 20, 2015
    85
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1333 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 129ms · UTC 20:07 · PVG 04:07 · LAX 12:07 · JFK 15:07
    ♥ Do have faith in what you're doing.