【问题标题】:truly unique random number generate by php?真正由php生成的唯一随机数?
【发布时间】:2017-06-08 03:08:23
【问题描述】:

我已经构建了一个 php 脚本来托管用户上传的大量图像,为图像文件名生成随机数以便将来不会有文件名冲突的最佳方法是什么?就像Imageshack一样。谢谢。

【问题讨论】:

  • 随机!=唯一。两者没有任何关系。随机数包括重复的数字——在数字序列中随机分布。
  • 图片是否与数据库记录相关联?如果是这样,您可以只使用主键作为文件名,因为它保证是唯一的。
  • 不查找数据库记录是否安全?我已经通过PHP查找该文件是否存在于文件夹中。
  • 当然你可以在数据库中查找它,但是 UUID 方法不需要,那何必呢?
  • 也许他无论如何都要在数据库中插入一条记录。

标签: php php4 flawed-concept


【解决方案1】:
$better_token = uniqid(md5(mt_rand()), true);

【讨论】:

    【解决方案2】:

    最简单的方法是为每个文件创建一个新的 GUID。

    http://www.php.net/manual/en/function.uniqid.php#65879

    【讨论】:

    • en.wikipedia.org/wiki/…。你更有可能被陨石击中。
    • 仍然不是避免使用真正独一无二的系统的理由。
    • @Lo'oris:没有被陨石击中听起来是个好理由。
    【解决方案3】:

    这是我实施您的解决方案的方式

    这个例子假设我想要

    • 获取一个列表,其中包含 50 个唯一且随机的数字,并且
    • 这个#列表来自0到1000的数字范围

    代码:

     //developed by www.fatphuc.com
    
     $array = array(); //define the array
    
     //set random # range
     $minNum = 0;
     $maxNum = 1000;
    
    // i just created this function, since we’ll be generating
    // # in various sections, and i just want to make sure that
    // if we need to change how we generate random #, we don’t 
    // have to make multiple changes to the codes everywhere. 
    // (basically, to prevent mistakes)
    
    function GenerateRandomNumber($minNum, $maxNum){
       return round(rand($minNum, $maxNum));
    }
    
    //generate 49 more random #s to give a total of 50 random #s
    for($i = 1; $i <= 49; $i++){
        $num1 = GenerateRandomNumber($minNum, $maxNum);   
            while(in_array($num1, $array)){
                $num1 = GenerateRandomNumber($minNum, $maxNum);
            }   
        $array[$i] = $num1;
    }
    
    asort($array); //just want to sort the array
    
    //this simply prints the list of #s in list style
    echo '<ol>';
    foreach ($array as $var){
        echo '<li>';
        echo $var;
        echo '</li>';
    }
    echo '</ol>';
    

    【讨论】:

      【解决方案4】:

      保留您之前生成的所有数字的持久列表(在数据库表或文件中),并检查新生成的数字是否不在列表中。如果您发现这非常昂贵,请在足够多的位上生成随机数,以保证非常低的冲突概率。

      您还可以使用增量方法来分配这些数字,例如基于当前时间的 timestamp_part 和 random_part 的串联,以确保在多个用户同时上传文件时不会发生冲突。

      【讨论】:

      • 此解决方案无法很好地扩展
      【解决方案5】:

      您可以按照上面的建议使用 microtime(),然后附加原始文件名的哈希值,以进一步避免在精确当代上传的(罕见)情况下发生冲突。

      【讨论】:

      • 我最喜欢这个。从当前时间戳、当前用户名、文件名和增量全局上传计数器创建的散列将是 100% 重复安全的。
      • 为什么?为什么不只使用增量全局计数器?这是所有这一切确保 0次碰撞的唯一部分。
      • 或者,正如我所建议的,只需创建一个名称而无需付出太多努力,然后在提交之前检查一下
      【解决方案6】:

      无论随机数生成器有多好,您的假设都存在一些缺陷,即随机值将是唯一的。此外,随机数生成器越好,计算结果所需的时间就越长。

      使用数据文件的哈希不是更好吗 - 这样您就可以获得检测重复提交的附加好处。

      如果检测重复已知不是问题,那么我仍然推荐这种方法,但会根据检测到的冲突修改输出(但使用比提出的计算方法便宜得多的计算方法Lo'oris) 例如

       $candidate_name=generate_hash_of_file($input_file);
       $offset=0;
       while ((file_exists($candidate_name . strrev($offset) && ($offset<50)) {
          $offset++;
       }
       if ($offset<50) {
          rename($input_file, $candidate_name . strrev($offset));
       } else {
          print "Congratulations - you've got the biggest storage network in the world by far!";
       }
      

      这将使您能够使用 sha1 哈希存储大约 25*2^63 个文件。

      关于如何生成哈希,将整个文件读入 PHP 可能会很慢(特别是如果您尝试将其全部读入单个字符串以对其进行哈希处理)。大多数 Linux/Posix/Unix 系统都带有像“md5sum”这样的工具,可以非常有效地从流中生成哈希。

      C.

      【讨论】:

        【解决方案7】:
        1. 伪造文件名
        2. 尝试打开该文件
        3. 如果存在,转到 1
        4. 创建文件

        【讨论】:

          【解决方案8】:

          也许使用基于时间戳的东西。有关详细信息,请参阅microtime 函数。或者uniqid根据当前时间生成唯一ID。

          【讨论】:

            【解决方案9】:

            保证唯一性不能是随机的。随机不能保证唯一。如果您想要唯一(没有随机),那么只需使用整数:0, 1, 2, ... 1235, 1236, 1237, ... 绝对唯一,但不是随机的。

            如果这不适合,那么你绝对可以拥有随机的外观。您对整数使用加密以使它们看起来是随机的。使用 DES 将为您提供 32 位数字,而使用 AES 将为您提供 64 位数字。使用任何一个来加密 0, 1, 2, ... 按顺序使用相同的密钥。您需要存储的只是密钥和下一个要加密的数字。因为加密是可逆的,所以保证加密后的数字是唯一的。

            如果 64 位或 32 位数字太大(32 位是 8 个十六进制数字),请查看格式保留加密,它会以一定的时间成本为您提供更小的大小范围。

            【讨论】:

              【解决方案10】:

              我的解决方案通常是图像内容的哈希 (MD5/SHA1/...)。这有一个额外的好处,如果人们两次上传相同的图像,您仍然只有一个图像在硬盘上,节省了一些空间(如果一个用户删除它并且另一个用户拥有图像,您必须确保该图像不会被删除使用相同的图像)。

              【讨论】:

              • 哈希,根据定义,不是唯一的。 (虽然当然不太可能发生碰撞)
              • 请注意,Git 使用哈希,并且发生冲突的可能性非常非常小。
              猜你喜欢
              • 1970-01-01
              • 2011-06-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-05-26
              相关资源
              最近更新 更多