如何可能生成一个随机的,唯一的字符串使用数字和字母用于验证链接?就像你在一个网站上创建了一个账户,它会给你发一封带有链接的电子邮件,你必须点击那个链接才能验证你的账户

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


当前回答

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

我根据Scott的回答创建了一个面向对象的解决方案:

<?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

我希望它能帮助到一些人。干杯!

其他回答

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();
    }

 }

这个函数将使用数字和字母生成一个随机键:

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

一个简单的解决方案是通过丢弃非字母数字字符将64进制转换为字母数字。

它使用random_bytes()来获得加密安全的结果。

function random_alphanumeric(int $length): string
{
    $result='';
    do
    {
        //Base 64 produces 4 characters for each 3 bytes, so most times this will give enough bytes in a single pass
        $bytes=random_bytes(($length+3-strlen($result))*2);
        //Discard non-alhpanumeric characters
        $result.=str_replace(['/','+','='],['','',''],base64_encode($bytes));
        //Keep adding characters until the string is long enough
        //Add a few extra because the last 2 or 3 characters of a base 64 string tend to be less diverse
    }while(strlen($result)<$length+3);
    return substr($result,0,$length);
}

编辑:我只是重新审视了一下,因为我需要一些更灵活的东西。这里有一个解决方案,执行得比上面的好一点,并提供了指定ASCII字符集的任何子集的选项:

<?php
class RandomText
{
    protected
        $allowedChars,
        //Maximum index to use
        $allowedCount,
        //Index values will be taken from a pool of this size
        //It is a power of 2 to keep the distribution of values even
        $distributionSize,
        //This many characters will be generated for each output character
        $ratio;
    /**
     * @param string $allowedChars characters to choose from
     */
    public function __construct(string $allowedChars)
    {
        $this->allowedCount = strlen($allowedChars);
        if($this->allowedCount < 1 || $this->allowedCount > 256) throw new \Exception('At least 1 and no more than 256 allowed character(s) must be specified.');
        $this->allowedChars = $allowedChars;
        //Find the power of 2 equal or greater than the number of allowed characters
        $this->distributionSize = pow(2,ceil(log($this->allowedCount, 2)));
        //Generating random bytes is the expensive part of this algorithm
        //In most cases some will be wasted so it is helpful to produce some extras, but not too many
        //On average, this is how many characters needed to produce 1 character in the allowed set
        //50% of the time, more characters will be needed. My tests have shown this to perform well.
        $this->ratio = $this->distributionSize / $this->allowedCount;
    }

    /**
     * @param int $length string length of required result
     * @return string random text
     */
    public function get(int $length) : string
    {
        if($length < 1) throw new \Exception('$length must be >= 1.');
        $result = '';
        //Keep track of result length to prevent having to compute strlen()
        $l = 0;
        $indices = null;
        $i = null;
        do
        {
            //Bytes will be used to index the character set. Convert to integers.
            $indices = unpack('C*', random_bytes(ceil(($length - $l) * $this->ratio)));
            foreach($indices as $i)
            {
                //Reduce to the smallest range that gives an even distribution
                $i %= $this->distributionSize;
                //If the index is within the range of characters, add one char to the string
                if($i < $this->allowedCount)
                {
                    $l++;
                    $result .= $this->allowedChars[$i];
                }
                if($l >= $length) break;
            }
        }while($l < $length);
        return $result;
    }
}

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

$key = md5(rand()); $key = md5(微时间());

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

<?php

echo md5(microtime(true).mt_Rand());

输出:

40a29479ec808ad4bcff288a48a25d5c

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