如何可能生成一个随机的,唯一的字符串使用数字和字母用于验证链接?就像你在一个网站上创建了一个账户,它会给你发一封带有链接的电子邮件,你必须点击那个链接才能验证你的账户
如何使用PHP生成其中一个?
如何可能生成一个随机的,唯一的字符串使用数字和字母用于验证链接?就像你在一个网站上创建了一个账户,它会给你发一封带有链接的电子邮件,你必须点击那个链接才能验证你的账户
如何使用PHP生成其中一个?
当前回答
<?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个字符。
其他回答
一个简单的解决方案是通过丢弃非字母数字字符将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;
}
}
投票最多的解决方案的面向对象版本
我根据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
我希望它能帮助到一些人。干杯!
PHP 7标准库提供了random_bytes($length)函数,该函数生成加密安全的伪随机字节。
例子:
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
上面的例子将输出类似于:
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
更多信息:http://php.net/manual/en/function.random-bytes.php
PHP 5(过时)
我只是在寻找如何解决这个相同的问题,但我也希望我的函数创建一个令牌,可以用于密码检索以及。这意味着我需要限制令牌的猜测能力。因为uniqid是基于时间的,而根据php.net“返回值与microtime()相差不大”,uniqid不符合条件。PHP建议使用openssl_random_pseudo_bytes()来生成加密安全的令牌。
一个快速、简短、直截了当的答案是:
bin2hex(openssl_random_pseudo_bytes($bytes))
它将生成一个长度= $bytes * 2的字母数字字符的随机字符串。不幸的是,这只有一个字母[a-f][0-9],但它是有效的。
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的字符串。
来源:http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php # 104322
我们可以用这两行代码生成唯一的字符串,已经测试了大约10000000次迭代
$sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
$uniqueString = md5(time().$sffledStr);
这个函数将使用数字和字母生成一个随机键:
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