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

不用数据库, PHP 每 10 分钟内生成一个恒定随机数,该怎样实现?

  •  2
     
  •   kisshere · 2021-08-23 10:19:23 +08:00 · 5672 次点击
    这是一个创建于 1190 天前的主题,其中的信息可能已经有所发展或是发生改变。

    api 请求一个 php 单文件,该 php 单文件(不调用数据库)每 10 分钟生成一个定值随机数,比如:

    8:00~8:10 请求该 php,只输出定值 23

    8:10~8:20 请求该 php,只输出定值 189

    8:20~8:30 请求该 php,只输出定值 3

    8:30~8:40 请求该 php,只输出定值 67

    ......

    这个该怎样实现?

    61 条回复    2021-08-25 09:02:50 +08:00
    y7E6IG8spV7TU8n7
        1
    y7E6IG8spV7TU8n7  
       2021-08-23 10:21:22 +08:00   ❤️ 3
    if elseif else
    Switch ....
    dallaslu
        2
    dallaslu  
       2021-08-23 10:22:01 +08:00
    8:00~8:10 请求该 php:base_convert(md5('8:00'), 16, 10) % MAX_VALUE

    8:10~8:20 请求该 php:base_convert(md5('8:10'), 16, 10) % MAX_VALUE
    yousabuk
        3
    yousabuk  
       2021-08-23 10:22:35 +08:00 via iPhone
    说的再详细写才好看
    yEhwG10ZJa83067x
        4
    yEhwG10ZJa83067x  
       2021-08-23 10:27:32 +08:00
    定值随机数 怎么理解?
    zoharSoul
        5
    zoharSoul  
       2021-08-23 10:28:49 +08:00   ❤️ 26
    定值还叫随机数?

    五彩斑斓的黑是吧
    8bit
        6
    8bit  
       2021-08-23 10:30:41 +08:00   ❤️ 1
    估计是不重复的随机数吧
    gfreezy
        7
    gfreezy  
       2021-08-23 10:33:37 +08:00   ❤️ 5
    把 10 分钟当作随机数的种子,同一个 10 分钟内返回的都是同一个随机数
    hauzi
        8
    hauzi  
       2021-08-23 10:34:22 +08:00
    直接用 cache 吧,10 分钟过期重新生成
    dinghmcn
        9
    dinghmcn  
       2021-08-23 10:34:47 +08:00
    要第一次随机,其后直接使用该值?
    每次先检查当前时段随机值是否存在,不存在就取一个随机值并保存起来
    oott123
        10
    oott123  
       2021-08-23 10:37:37 +08:00   ❤️ 1
    <?php
    define('MY_SUPER_SECRET_CONSTANT', 123456789);
    srand(intval(time() / 600) + MY_SUPER_SECRET_CONSTANT);
    echo rand(0, 500);
    oott123
        11
    oott123  
       2021-08-23 10:38:07 +08:00   ❤️ 1
    以及我给的方法非常不安全(意味着该随机数可推测)。
    keepeye
        12
    keepeye  
       2021-08-23 10:40:12 +08:00
    楼主的意思是,10 分钟内只生成一次随机数,多次请求返回缓存值。所以用缓存就行了啊,往 /tmp/目录下写个缓存文件,把时间、数值记录进去,每次读取,判断时间决定要不要重新生成
    boboliu
        13
    boboliu  
       2021-08-23 10:40:42 +08:00 via Android   ❤️ 1
    你是不是在找:totp
    kisshere
        14
    kisshere  
    OP
       2021-08-23 10:41:07 +08:00
    @justrand
    @zoharSoul 是根据时间段返回不同的随机数,时间段的最小区间长度是 10 分钟,该区间内,输出恒定数
    kisshere
        15
    kisshere  
    OP
       2021-08-23 10:41:47 +08:00
    @keepeye 不往硬盘写文件,只用纯算法实现
    JKeita
        16
    JKeita  
       2021-08-23 10:46:41 +08:00
    $t = time();
    $t = $t - $t%600;
    srand($t);
    $v = rand();
    echo $v;
    keepeye
        17
    keepeye  
       2021-08-23 10:48:31 +08:00
    @kisshere 那你可以用 mt_srand 播种,种子就是时间拼成的整数
    pengtdyd
        18
    pengtdyd  
       2021-08-23 10:49:06 +08:00
    大胆猜测一下,这个问题的背后必然有一个伞兵的产品经理
    hxnets
        19
    hxnets  
       2021-08-23 10:50:18 +08:00
    恒定随机数???
    finull
        20
    finull  
       2021-08-23 10:51:47 +08:00
    @kisshere @boboliu 提到的 TOTP 值得考虑
    JKeita
        21
    JKeita  
       2021-08-23 10:51:54 +08:00
    srand 和 mt_srand 都是设置随机数种子,设置定值产生的随机数就一样了。
    InDom
        22
    InDom  
       2021-08-23 10:52:13 +08:00
    https://imgur.com/M5Zdlve

    以整时间作为随机数种子,同 #11,非常不安全,随机数可推测,某种理论来说,这已经不是随机数了。
    xytest
        23
    xytest  
       2021-08-23 10:55:59 +08:00
    生成一个 写到 redis 十分钟过期。
    RRRoger
        24
    RRRoger  
       2021-08-23 11:25:37 +08:00
    生成随机数的目的就是不可预测。

    你可以根据时间特性写个简单的算法。

    比如在 8:00~8:10 你取 08:05 把所有的值(0,8,0,5)加起来得 13 然后通过 md5 算法, 从后往前取后面的整数位。

    至于整数位的个数,你可以用时间里数字 0 的个数。

    这样肉眼不可预测, 也能达到随机效果
    lxz6597863
        25
    lxz6597863  
       2021-08-23 11:36:50 +08:00
    now := time.Now().Unix()
    fmt.Println(now - (now % 600))

    //600 秒 == 10 分钟
    boboliu
        26
    boboliu  
       2021-08-23 12:19:43 +08:00
    boboliu
        27
    boboliu  
       2021-08-23 12:22:35 +08:00
    ganbuliao
        28
    ganbuliao  
       2021-08-23 12:26:16 +08:00
    那就很简单 8:00~8:10 就用 8:00 做这个加密算法的 value 不就行了 加密算法 就 什么随便的加减乘除一下 在截取一下就搞定了
    summerLast
        29
    summerLast  
       2021-08-23 12:34:57 +08:00
    日期取 yyyyMMddHHm
    summerLast
        30
    summerLast  
       2021-08-23 12:35:29 +08:00
    @summerLast 在复杂点 求个 hash
    summerLast
        31
    summerLast  
       2021-08-23 12:36:03 +08:00
    @summerLast 在复杂点加盐 求个 hash
    wavingclear
        32
    wavingclear  
       2021-08-23 12:46:23 +08:00
    抄一下网银实体数字密保、steam 手机验证器之类的离线随机数生成器的算法,他们几十秒更新一次你 10 分钟更新一次。
    binux
        33
    binux  
       2021-08-23 12:54:45 +08:00 via Android
    随便找一个随机数算法,取第时间 offset/10min 个数就行了。
    bghtyu
        34
    bghtyu  
       2021-08-23 12:59:06 +08:00 via Android
    就是 totp,Google 身份验证器那种
    eason1874
        35
    eason1874  
       2021-08-23 13:30:05 +08:00
    不用自己实现,找个 TOTP 类,把间隔时间(默认是 30 秒或 60 秒)改成 600 秒就 OK 了
    neptuno
        36
    neptuno  
       2021-08-23 13:52:41 +08:00
    是所有人都返回同一个随机数还是每个人随机数不同?所有人的话,生成一个随机数,缓存下来,后面的十分钟就返回这个随机数。每个人不同的话 totp
    feikeq
        37
    feikeq  
       2021-08-23 14:16:38 +08:00
    你是不是要做动态令牌。。。。。我以前做过动态密码每天密码不一样的那种
    mingl0280
        38
    mingl0280  
       2021-08-23 14:30:31 +08:00 via Android
    yyyyMMddHH 加上分钟取整加上 uid 哈希。totp 啊……
    Lemeng
        39
    Lemeng  
       2021-08-23 15:35:50 +08:00
    需求写的不是特别清楚
    fuxkcsdn
        40
    fuxkcsdn  
       2021-08-23 15:48:57 +08:00 via iPhone
    rsa 加密当前时间戳,保证恒定,保证随机

    bcmod(bcpow(time(), $e), $n)

    其中的 e 和 n 参数定义见
    https://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

    https://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html
    fuxkcsdn
        41
    fuxkcsdn  
       2021-08-23 15:52:30 +08:00 via iPhone
    p.s.不要试图用 bcmath 拓展进行解密,超级慢。要解密的话用 gmp 拓展(只是相对 bcmath 快而已,数值大的话,解密也是慢)
    tabris17
        42
    tabris17  
       2021-08-23 15:57:54 +08:00
    return (int)(time() / 10)
    bixchen
        43
    bixchen  
       2021-08-23 16:12:16 +08:00
    单文件,反正都上服务器了。弄个 redis ttl 10min 是否存在,存在 return 不存在 create 然后 return
    imluvian
        44
    imluvian  
       2021-08-23 16:26:11 +08:00 via Android
    楼主你这是想抽奖作弊啊?
    Coder89757
        45
    Coder89757  
       2021-08-23 17:00:20 +08:00
    面试题请自己做,谢谢。。。
    Juszoe
        46
    Juszoe  
       2021-08-23 17:10:34 +08:00
    每十分钟生成一个新的随机数,保存到全局变量里。
    建议楼主描述清楚需求,不然又成一个 X-Y problem
    shellus
        47
    shellus  
       2021-08-23 17:19:55 +08:00
    其实你就是想生成一个动态的加密串,防止前端的加密串被拿去一直用。
    所以每 10 分钟这个加密串就禁用了。前端必须重新获取,是吧?
    不要重复造轮子了,这就是 JWT Auth
    Hardrain
        48
    Hardrain  
       2021-08-23 17:32:22 +08:00
    时间戳 /600 作为 random seed?
    crab
        49
    crab  
       2021-08-23 17:42:35 +08:00
    对时间间隔取余来固定种子数值
    yogogo
        50
    yogogo  
       2021-08-23 20:49:16 +08:00   ❤️ 1
    不要碰灰产
    w3cll
        51
    w3cll  
       2021-08-23 21:54:21 +08:00
    @yogogo 看来你有故事
    RRyo
        52
    RRyo  
       2021-08-23 22:28:31 +08:00 via iPhone
    时间戳除你需要的间隔,做种子生成随机数,更工程化的可以参考 2FA 的那套东西,很多现成的库
    EscYezi
        53
    EscYezi  
       2021-08-23 22:34:41 +08:00 via iPhone
    具体场景是怎么样的?
    yuzo555
        54
    yuzo555  
       2021-08-23 22:44:00 +08:00
    用 hash 算法,比如 md5,原文为 intval(time() / 600) 加上一个很长的盐值,然后取十六进制格式的最后几位(具体几位取决于你想要的数字大小范围),然后转为十进制数。
    hefish
        55
    hefish  
       2021-08-23 23:32:51 +08:00
    难得大家如此热情,我觉着这个需求莫名其妙,非常奇葩。 没有责怪 LZ 的意思,纯粹觉着需求奇葩。
    huskyui
        56
    huskyui  
       2021-08-24 00:15:43 +08:00
    每天凌晨,可以预先生成一个满足数量的数组,然后打乱.根据时间点
    GeruzoniAnsasu
        57
    GeruzoniAnsasu  
       2021-08-24 07:51:34 +08:00
    @zoharSoul

    鉴于本楼 lz 的问题已经得到解答了,歪个题,看看这算不算「五彩斑斓的黑」


    gitdoit
        58
    gitdoit  
       2021-08-24 10:20:13 +08:00
    题目半天没读明白,还有这么多人回答, 我觉得我脑子有问题
    zjsxwc
        59
    zjsxwc  
       2021-08-24 10:46:40 +08:00
    如果不能用数据库等存储(文件系统也算数据库)的话,

    每 10 秒恒定就说明你这个随机数是由你当前时间确定的,于是你这个随机根本就不是随机数!

    如果不是随机数,那么解决楼主需求的办法确实只有用 rsa 非对称加密办法了,最多就是密钥每天换一个新的。
    pckillers
        60
    pckillers  
       2021-08-24 12:18:04 +08:00
    @zjsxwc 把年月日也加进判断不就得了。 日期 + 时间(精确到 10 分钟) + 字符 做个 MD5 再随便想个公式变回数字。 也看起来差不多像随机数了。
    raysonlu
        61
    raysonlu  
       2021-08-25 09:02:49 +08:00
    就题目看,明显就 if else 完事,但感觉明显就是题目需求都没有说清楚
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2359 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:09 · PVG 00:09 · LAX 08:09 · JFK 11:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.