首页 文章

PHP:如何生成随机,唯一,字母数字字符串?

提问于
浏览
312

如何使用数字和字母生成随机的唯一字符串以用于验证链接?就像您在网站上创建一个帐户一样,它会向您发送一封带有链接的电子邮件,您必须单击该链接才能验证您的帐户...是的......其中一个 .

如何使用PHP生成其中一个?

Update: 刚想起uniqid() . 它's a PHP function that generates a unique identifier based on the current time in microseconds. I think I'将使用它 .

25 回答

  • 86

    在阅读前面的例子之后我想出了这个:

    protected static $nonce_length = 32;
    
    public static function getNonce()
    {
        $chars = array();
        for ($i = 0; $i < 10; $i++)
            $chars = array_merge($chars, range(0, 9), range('A', 'Z'));
        shuffle($chars);
        $start = mt_rand(0, count($chars) - self::$nonce_length);
        return substr(join('', $chars), $start, self::$nonce_length);
    }
    

    我复制10次数组[0-9,AZ]并随机播放元素,在我得到substr()的随机起点更加'有创意':)你可以将[az]和其他元素添加到数组中,重复或多或少,比我更有创意

  • 1

    我相信所有现有想法的问题在于它们可能是独一无二的,但并非绝对独特(正如Dariusz Walczak对loletech的回复所指出的那样) . 我有一个实际上独一无二的解决方案 . 它要求您的脚本具有某种内存 . 对我来说这是一个SQL数据库 . 你也可以简单地写一个文件 . 有两种实现:

    第一种方法:有两个字段而不是一个提供唯一性的字段 . 第一个字段是一个非随机但是唯一的ID号(第一个ID是1,第二个是......) . 如果您使用的是SQL,只需使用AUTO_INCREMENT属性定义ID字段即可 . 第二个字段不是唯一的,而是随机的 . 这可以通过人们已经提到的任何其他技术生成 . 斯科特的想法很好,但是md5很方便,对于大多数用途来说可能还不错:

    $random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());
    

    第二种方法:基本上是相同的想法,但最初选择将生成的最大字符串数 . 这可能只是一个非常大的数字,如万亿 . 然后做同样的事情,生成一个ID,但零填充它,以便所有ID都是相同的位数 . 然后只是将ID与随机字符串连接起来 . 对于大多数用途来说它足够随机,但ID部分将确保它也是唯一的 .

  • 419

    我'm late but I'这里有一些基于Scott's answer提供的功能的好研究数据 . 因此,我为这个为期5天的自动测试设置了一个Digital Ocean Droplet,并将生成的唯一字符串存储在MySQL数据库中 .

    在这个测试期间,我使用了5种不同的长度(5,10,15,20,50)和每个长度插入的/0.5百万条记录 . 在我的测试期间,只有长度5生成/ -3K重复50万,其余长度没有产生任何重复 . 所以我们可以说,如果我们使用Scott的函数长度为15或更长,那么我们就可以生成高度可靠的唯一字符串 . 这是显示我的研究数据的表格:

    enter image description here

    我希望这有帮助 .

  • 12

    这是最适合您的唯一ID生成器 . 我做的 .

    <?php
    $d=date ("d");
    $m=date ("m");
    $y=date ("Y");
    $t=time();
    $dmt=$d+$m+$y+$t;    
    $ran= rand(0,10000000);
    $dmtran= $dmt+$ran;
    $un=  uniqid();
    $dmtun = $dmt.$un;
    $mdun = md5($dmtran.$un);
    $sort=substr($mdun, 16); // if you want sort length code.
    
    echo $mdun;
    ?>
    

    你可以根据自己的喜好回复任何'var' . 但$ mdun更好,你可以将md5替换为sha1以获得更好的代码,但这将是非常长的,你可能不需要 .

    谢谢 .

  • 0
    <?php
    function generateRandomString($length = 11) {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    
    }
    
    ?>
    

    上面的函数会生成一个长度为11个字符的随机字符串 .

  • 22

    使用下面的代码生成11个字符的随机数,或根据您的要求更改数字 .

    $randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);
    
    or we can use custom function to generate the random number
    
     function randomNumber($length){
         $numbers = range(0,9);
         shuffle($numbers);
         for($i = 0;$i < $length;$i++)
            $digits .= $numbers[$i];
         return $digits;
     }
    
     //generate random number
     $randomNum=randomNumber(11);
    
  • 257

    我认为这是最好的使用方法 .

    str_shuffle(md5(rand(0,100000)))
    
  • 4

    此函数将使用数字和字母生成随机密钥:

    function random_string($length) {
        $key = '';
        $keys = array_merge(range(0, 9), range('a', 'z'));
    
        for ($i = 0; $i < $length; $i++) {
            $key .= $keys[array_rand($keys)];
        }
    
        return $key;
    }
    
    echo random_string(50);
    

    输出示例:

    zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8
    
  • 7

    您可以使用此代码,我希望它对您有所帮助 .

    function rand_code($len)
    {
     $min_lenght= 0;
     $max_lenght = 100;
     $bigL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     $smallL = "abcdefghijklmnopqrstuvwxyz";
     $number = "0123456789";
     $bigB = str_shuffle($bigL);
     $smallS = str_shuffle($smallL);
     $numberS = str_shuffle($number);
     $subA = substr($bigB,0,5);
     $subB = substr($bigB,6,5);
     $subC = substr($bigB,10,5);
     $subD = substr($smallS,0,5);
     $subE = substr($smallS,6,5);
     $subF = substr($smallS,10,5);
     $subG = substr($numberS,0,5);
     $subH = substr($numberS,6,5);
     $subI = substr($numberS,10,5);
     $RandCode1 = str_shuffle($subA.$subD.$subB.$subF.$subC.$subE);
     $RandCode2 = str_shuffle($RandCode1);
     $RandCode = $RandCode1.$RandCode2;
     if ($len>$min_lenght && $len<$max_lenght)
     {
     $CodeEX = substr($RandCode,0,$len);
     }
     else
     {
     $CodeEX = $RandCode;
     }
     return $CodeEX;
    }
    

    有关Random code generator in PHP的详细信息

  • -1

    对于真正随机的字符串,您可以使用

    <?php
    
    echo md5(microtime(true).mt_Rand());
    

    产出:

    40a29479ec808ad4bcff288a48a25d5c
    

    因此,即使您尝试在同一时间多次生成字符串,您也会获得不同的输出 .

  • 0

    您可以使用UUID(通用唯一标识符),它可以用于任何目的,从用户身份验证字符串到支付交易ID .

    UUID是16个八位字节(128位)的数字 . 在其规范形式中,UUID由32个十六进制数字表示,显示在由连字符分隔的五个组中,格式为8-4-4-4-12,总共36个字符(32个字母数字字符和四个连字符) .

    function generate_uuid() {
        return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
            mt_rand( 0, 0xffff ),
            mt_rand( 0, 0x0C2f ) | 0x4000,
            mt_rand( 0, 0x3fff ) | 0x8000,
            mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
        );
    
    }
    

    //调用函数

    $transationID = generate_uuid();
    

    一些示例输出将如下:

    E302D66D-87E3-4450-8CB6-17531895BF14
    22D288BC-7289-442B-BEEA-286777D559F2
    51B4DE29-3B71-4FD2-9E6C-071703E1FF31
    3777C8C6-9FF5-4C78-AAA2-08A47F555E81
    54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
    60F75C7C-1AE3-417B-82C8-14D456542CD7
    8DE0168D-01D3-4502-9E59-10D665CEBCB2
    

    希望它能帮助将来的某个人:)

  • 0

    安全声明:如果随机性质量会影响应用程序的安全性,则不应使用此解决方案 . 特别是,rand()和uniqid()不是加密安全的随机数生成器 . 请参阅斯科特关于安全替代方案的答案 .

    如果您不需要它随着时间的推移绝对独特:

    md5(uniqid(rand(), true))

    否则(假设您已为用户确定了唯一的登录名):

    md5(uniqid($your_user_login, true))
    
  • 6

    斯科特,是的,你是非常好的解决方案!谢谢 .

    我还需要为每个用户生成唯一的API令牌 . 以下是我的方法,我使用了用户信息(Userid和Username):

    public function generateUniqueToken($userid, $username){
    
            $rand = mt_rand(100,999);
        $md5 = md5($userid.'!(&^ 532567_465 ///'.$username);
    
        $md53 = substr($md5,0,3);
        $md5_remaining = substr($md5,3);
    
        $md5 = $md53. $rand. $userid. $md5_remaining;
    
        return $md5;
    }
    

    请看看,让我知道我能做些什么改进 . 谢谢

  • 0
    function random_string($length = 8) {
        $alphabets = range('A','Z');
        $numbers = range('0','9');
        $additional_characters = array('_','=');
        $final_array = array_merge($alphabets,$numbers,$additional_characters);
           while($length--) {
          $key = array_rand($final_array);
    
          $password .= $final_array[$key];
                            }
      if (preg_match('/[A-Za-z0-9]/', $password))
        {
         return $password;
        }else{
        return  random_string();
        }
    
     }
    
  • -1

    这是我'm using on one of my projects, it'工作得很好,它生成 UNIQUE RANDOM TOKEN

    $timestampz=time();
    
    function generateRandomString($length = 60) {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }
    
    
    $tokenparta = generateRandomString();
    
    
    $token = $timestampz*3 . $tokenparta;
    
    echo $token;
    

    请注意,我将时间戳乘以3,以便为用户可能想知道如何生成此令牌的人造成混淆;)

    我希望它有帮助:)

  • 29

    我只是在研究如何解决同样的问题,但我也希望我的函数能够创建一个可用于密码检索的令牌 . 这意味着我需要限制令牌猜测的能力 . 因为uniqid是基于时间的,并且根据php.net "the return value is little different from microtime()", uniqid 不符合标准 . PHP建议使用 openssl_random_pseudo_bytes() 来生成加密安全令牌 .

    一个快速,简短和重点的答案是:

    bin2hex(openssl_random_pseudo_bytes($bytes))
    

    这将产生一个长度为= $ bytes * 2的字母数字字符的随机字符串 . 不幸的是,这只有 [a-f][0-9] 的字母表,但它有效 .


    以下是我能做出的最强大的功能,满足标准(这是Erik答案的实施版本) .

    function crypto_rand_secure($min, $max)
    {
        $range = $max - $min;
        if ($range < 1) return $min; // not so random...
        $log = ceil(log($range, 2));
        $bytes = (int) ($log / 8) + 1; // length in bytes
        $bits = (int) $log + 1; // length in bits
        $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter; // discard irrelevant bits
        } while ($rnd > $range);
        return $min + $rnd;
    }
    
    function getToken($length)
    {
        $token = "";
        $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
        $codeAlphabet.= "0123456789";
        $max = strlen($codeAlphabet); // edited
    
        for ($i=0; $i < $length; $i++) {
            $token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
        }
    
        return $token;
    }
    

    crypto_rand_secure($min, $max) 作为 rand()mt_rand 的替代品 . 它使用openssl_random_pseudo_bytes来帮助创建$ min和$ max之间的随机数 .

    getToken($length) 创建要在令牌中使用的字母表,然后创建长度为 $length 的字符串 .

    EDIT: 我忽略了引用来源 - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

    EDIT (PHP7): 随着PHP7的发布,标准库现在有两个新函数可以替换/改进/简化上面的crypto_rand_secure函数 . random_bytes($length)random_int($min, $max)

    http://php.net/manual/en/function.random-bytes.php

    http://php.net/manual/en/function.random-int.php

    例:

    function getToken($length){
         $token = "";
         $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
         $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
         $codeAlphabet.= "0123456789";
         $max = strlen($codeAlphabet); // edited
    
        for ($i=0; $i < $length; $i++) {
            $token .= $codeAlphabet[random_int(0, $max-1)];
        }
    
        return $token;
    }
    
  • 22

    这是一个简单的函数,允许您生成包含字母和数字(字母数字)的随机字符串 . 您还可以限制字符串长度 . 这些随机字符串可用于各种目的,包括:推荐代码,促销代码,优惠券代码 . 函数依赖于以下PHP函数: base_convert, sha1, uniqid, mt_rand

    function random_code($length)
    {
      return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
    }
    
    echo random_code(6);
    
    /*sample output
    * a7d9e8
    * 3klo93
    */
    
  • 1

    我喜欢在处理验证链接时使用哈希键 . 我建议使用使用MD5的microtime和散列,因为没有理由为什么键应该是相同的,因为它基于microtime的哈希 .

    • $key = md5(rand());

    • $key = md5(microtime());

  • -2
    • 使用您喜欢的随机数生成器生成随机数

    • 将其除以并除以得到与代码字母表中的字符数相匹配的数字

    • 在代码字母表中获取该索引处的项目 .

    • 从1)重复,直到你有你想要的长度

    例如(伪代码)

    int myInt = random(0, numcharacters)
    char[] codealphabet = 'ABCDEF12345'
    char random = codealphabet[i]
    repeat until long enough
    
  • 2

    面向对象版本的最高投票解决方案

    我基于_322163的答案创建了一个面向对象的解决方案:

    <?php
    
    namespace Utils;
    
    /**
     * Class RandomStringGenerator
     * @package Utils
     *
     * Solution taken from here:
     * http://stackoverflow.com/a/13733588/1056679
     */
    class RandomStringGenerator
    {
        /** @var string */
        protected $alphabet;
    
        /** @var int */
        protected $alphabetLength;
    
    
        /**
         * @param string $alphabet
         */
        public function __construct($alphabet = '')
        {
            if ('' !== $alphabet) {
                $this->setAlphabet($alphabet);
            } else {
                $this->setAlphabet(
                      implode(range('a', 'z'))
                    . implode(range('A', 'Z'))
                    . implode(range(0, 9))
                );
            }
        }
    
        /**
         * @param string $alphabet
         */
        public function setAlphabet($alphabet)
        {
            $this->alphabet = $alphabet;
            $this->alphabetLength = strlen($alphabet);
        }
    
        /**
         * @param int $length
         * @return string
         */
        public function generate($length)
        {
            $token = '';
    
            for ($i = 0; $i < $length; $i++) {
                $randomKey = $this->getRandomInteger(0, $this->alphabetLength);
                $token .= $this->alphabet[$randomKey];
            }
    
            return $token;
        }
    
        /**
         * @param int $min
         * @param int $max
         * @return int
         */
        protected function getRandomInteger($min, $max)
        {
            $range = ($max - $min);
    
            if ($range < 0) {
                // Not so random...
                return $min;
            }
    
            $log = log($range, 2);
    
            // Length in bytes.
            $bytes = (int) ($log / 8) + 1;
    
            // Length in bits.
            $bits = (int) $log + 1;
    
            // Set all lower bits to 1.
            $filter = (int) (1 << $bits) - 1;
    
            do {
                $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
    
                // Discard irrelevant bits.
                $rnd = $rnd & $filter;
    
            } while ($rnd >= $range);
    
            return ($min + $rnd);
        }
    }
    

    用法

    <?php
    
    use Utils\RandomStringGenerator;
    
    // Create new instance of generator class.
    $generator = new RandomStringGenerator;
    
    // Set token length.
    $tokenLength = 32;
    
    // Call method to generate random string.
    $token = $generator->generate($tokenLength);
    

    自定义字母

    如果需要,您可以使用自定义字母 . 只需将带有受支持字符的字符串传递给构造函数或setter:

    <?php
    
    $customAlphabet = '0123456789ABCDEF';
    
    // Set initial alphabet.
    $generator = new RandomStringGenerator($customAlphabet);
    
    // Change alphabet whenever needed.
    $generator->setAlphabet($customAlphabet);
    

    这是输出样本

    SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
    q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
    I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
    AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
    duoRF6gAawNOEQRICnOUNYmStWmOpEgS
    sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
    eVywMdYXczuZmHaJ50nIVQjOidEVkVna
    baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
    iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
    OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa
    

    我希望它会帮助某人 . 干杯!

  • 0

    通过删除不必要的循环来简化上面的Scotts代码,这种循环正在慢慢地减慢并且不会比仅仅调用openssl_random_pseudo_bytes更安全

    function crypto_rand_secure($min, $max)
    {
     $range = $max - $min;
     if ($range < 1) return $min; // not so random...
     $log = ceil(log($range, 2));
     $bytes = (int) ($log / 8) + 1; // length in bytes
     $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
     return $min + $rnd%$range;
    }
    
    function getToken($length)
    {
     return bin2hex(openssl_random_pseudo_bytes($length)
    }
    
  • 1

    如果要在PHP中生成唯一字符串,请尝试以下操作 .

    md5(uniqid().mt_rand());
    

    在这,

    uniqid() - 它将生成唯一的字符串 . 此函数将基于时间戳的唯一标识符作为字符串返回 .

    mt_rand() - 生成随机数 .

    md5() - 它将生成哈希字符串 .

  • 0

    我用这个单线:

    base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));
    

    其中length是所需字符串的长度(可被4整除,否则会向下舍入到最接近4的整数)

  • 0

    我们可以使用这两行代码生成唯一的字符串,已经测试了大约10000000次迭代

    $sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
        $uniqueString = md5(time().$sffledStr);
    
  • 1

    这是我使用的:

    md5(time() . rand());    
    // Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b
    

相关问题