如何使用 PHP 创建随机字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/853813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a random string using PHP?
提问by Keith Donegan
I know that the rand function in PHP generates random integers, but what is the best way to generate a random string such as:
我知道 PHP 中的 rand 函数会生成随机整数,但是生成随机字符串的最佳方法是什么,例如:
Original string, 9 chars
原始字符串,9 个字符
$string = 'abcdefghi';
Example random string limiting to 6 chars
示例随机字符串限制为 6 个字符
$string = 'ibfeca';
UPDATE: I have found tons of these types of functions, basically I'm trying to understand the logic behind each step.
更新:我发现了大量这些类型的函数,基本上我试图理解每一步背后的逻辑。
UPDATE: The function should generate any amount of chars as required.
更新:该函数应根据需要生成任意数量的字符。
Please comment the parts if you reply.
如果您回复,请评论部分。
回答by Gumbo
If you want to allow repetitive occurences of characters, you can use this function:
如果你想允许字符重复出现,你可以使用这个函数:
function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
$str = '';
$count = strlen($charset);
while ($length--) {
$str .= $charset[mt_rand(0, $count-1)];
}
return $str;
}
The basic algorithm is to generate <length> times a random number between 0 and <number of characters> ? 1 we use as index to pick a character from our set and concatenate those characters. The 0 and <number of characters> ? 1 bounds represent the bounds of the $charsetstring as the first character is addressed with $charset[0]and the last with $charset[count($charset) - 1].
基本算法是生成<长度>乘以0到<字符数>之间的随机数?1 我们用作索引从我们的集合中选择一个字符并连接这些字符。0 和 <字符数> ? 1 边界表示$charset字符串的边界,因为第一个字符用 寻址,$charset[0]最后一个字符用 寻址$charset[count($charset) - 1]。
回答by Chad Birch
Well, you didn't clarify all the questions I asked in my comment, but I'll assume that you want a function that can take a string of "possible" characters and a length of string to return. Commented thoroughly as requested, using more variables than I would normally, for clarity:
好吧,你没有澄清我在评论中提出的所有问题,但我假设你想要一个函数,它可以接受一串“可能”的字符和一段字符串返回。为清楚起见,按照要求进行了彻底评论,使用了比我平时更多的变量:
function get_random_string($valid_chars, $length)
{
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
To call this function with your example data, you'd call it something like:
要使用您的示例数据调用此函数,您可以将其命名为:
$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);
Note that this function doesn't check for uniqueness in the valid chars passed to it. For example, if you called it with a valid chars string of 'AAAB', it would be three times more likely to choose an A for each letter as a B. That could be considered a bug or a feature, depending on your needs.
请注意,此函数不会检查传递给它的有效字符的唯一性。例如,如果您使用有效字符字符串 调用它,'AAAB'则为每个字母选择 A 作为 B 的可能性要高出三倍。这可能被视为错误或功能,具体取决于您的需要。
回答by tasmaniski
My favorite:
我最喜欢的:
echo substr(md5(rand()), 0, 7);
回答by ircmaxell
So, let me start off by saying USE A LIBRARY. Many exist:
所以,让我先说USE A LIBRARY。许多存在:
The core of the problem is almost every answer in this page is susceptible to attack. mt_rand(), rand(), lcg_value()and uniqid()are all vulnerable to attack.
问题的核心是几乎这个页面中的每个答案都容易受到攻击。mt_rand(), rand(),lcg_value()和uniqid()都容易受到攻击。
A good system will use /dev/urandomfrom the filesystem, or mcrypt_create_iv()(with MCRYPT_DEV_URANDOM) or openssl_pseudo_random_bytes(). Which all of the above do. PHP 7 will come with two new functionsrandom_bytes($len)and random_int($min, $max)that are also safe.
一个好的系统将使用/dev/urandom来自文件系统,或mcrypt_create_iv()(与MCRYPT_DEV_URANDOM)或openssl_pseudo_random_bytes(). 以上都是这样做的。PHP 7将带着两个新的功能random_bytes($len)和random_int($min, $max)那也是安全的。
Be aware that most of those functions (except random_int()) return "raw strings" meaning they can contain any ASCII character from 0 - 255. If you want a printable string, I'd suggest running the result through base64_encode().
请注意,大多数这些函数(除了random_int())返回“原始字符串”,这意味着它们可以包含来自0 - 255. 如果你想要一个可打印的字符串,我建议通过base64_encode().
回答by ircmaxell
function generate_random_string($name_length = 8) {
$alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}
Updated the code as per mzhang's great suggestion in the comments below.
根据mzhang在下面评论中的伟大建议更新了代码。
回答by Sliq
A better and updated version of @taskamiski's excellent answer:
@taskamiski 的优秀答案的更好和更新版本:
Better version, using mt_rand()instead of rand():
更好的版本,使用mt_rand()代替rand():
echo md5(mt_rand()); // 32 char string = 128bit
Even better, for longer strings, using the hash()function that allows to select hashing algorithmns:
更好的是,对于更长的字符串,使用hash()允许选择散列算法的函数:
echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string
If you want to cut the result down to let's say 50 chars, do it like this:
如果您想将结果减少到 50 个字符,请这样做:
echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string
回答by Imran
Joining characters at the end should be more efficient that repeated string concatenation.
最后加入字符应该比重复字符串连接更有效。
Edit #1: Added option to avoid character repetition.
编辑 #1:添加了避免字符重复的选项。
Edit #2: Throws exception to avoid getting into infinite loop if $norepeat is selected and $len is greater than the charset to pick from.
编辑 #2:如果选择了 $norepeat 并且 $len 大于要从中选择的字符集,则抛出异常以避免进入无限循环。
Edit #3: Uses array keys to store picked random characters when $norepeat is selected, as associative array key lookup is faster than linearly searching the array.
编辑#3:使用数组键在选择$ norepeat时存储挑选的随机字符,因为关联数组密钥查找速度比线性搜索阵列更快。
function rand_str($len, $norepeat = true)
{
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$max = strlen($chars) - 1;
if ($norepeat && len > $max + 1) {
throw new Exception("Non repetitive random string can't be longer than charset");
}
$rand_chars = array();
while ($len) {
$picked = $chars[mt_rand(0, $max)];
if ($norepeat) {
if (!array_key_exists($picked, $rand_chars)) {
$rand_chars[$picked] = true;
$len--;
}
}
else {
$rand_chars[] = $picked;
$len--;
}
}
return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);
}
回答by Akhilraj N S
this will generate random string
这将生成随机字符串
function generateRandomString($length=10) {
$original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
$original_string = implode("", $original_string);
return substr(str_shuffle($original_string), 0, $length);
}
echo generateRandomString(6);
回答by zeeks
I think I will add my contribution here as well.
我想我也会在这里添加我的贡献。
function random_string($length) {
$bytes_1 = openssl_random_pseudo_bytes($length);
$hex_1 = bin2hex($bytes_1);
$random_numbers = substr(sha1(rand()), 0, $length);
$bytes_2 = openssl_random_pseudo_bytes($length);
$hex_2 = bin2hex($bytes_2);
$combined_chars = $hex_1 . $random_numbers . $hex_2;
$chars_crypted = hash('sha512', $combined_chars);
return $chars_crypted;
}
Thanks
谢谢
回答by Scott Arciszewski
What do you need a random string for?
你需要一个随机字符串做什么?
Is this going to be used for anything remotely analogous to a password?
这将用于远程类似于密码的任何东西吗?
If your random string requires anysecurity properties at all, you should use PHP 7's random_int()function instead of all the insecure mt_rand()answers in this thread.
如果您的随机字符串根本需要任何安全属性,您应该使用 PHP 7 的random_int()函数而不是mt_rand()该线程中的所有不安全答案。
/**
* Generate a random string
*
* @link https://paragonie.com/b/JvICXzh_jhLyt4y3
*
* @param int $length - How long should our random string be?
* @param string $charset - A string of all possible characters to choose from
* @return string
*/
function random_str($length = 32, $charset = 'abcdefghijklmnopqrstuvwxyz')
{
// Type checks:
if (!is_numeric($length)) {
throw new InvalidArgumentException(
'random_str - Argument 1 - expected an integer'
);
}
if (!is_string($charset)) {
throw new InvalidArgumentException(
'random_str - Argument 2 - expected a string'
);
}
if ($length < 1) {
// Just return an empty string. Any value < 1 is meaningless.
return '';
}
// This is the maximum index for all of the characters in the string $charset
$charset_max = strlen($charset) - 1;
if ($charset_max < 1) {
// Avoid letting users do: random_str($int, 'a'); -> 'aaaaa...'
throw new LogicException(
'random_str - Argument 2 - expected a string at least 2 characters long'
);
}
// Now that we have good data, this is the meat of our function:
$random_str = '';
for ($i = 0; $i < $length; ++$i) {
$r = random_int(0, $charset_max);
$random_str .= $charset[$r];
}
return $random_str;
}
If you aren't on PHP 7 yet (which is probably the case, as it hasn't been released as of this writing), then you'll want paragonie/random_compat, which is a userland implementation of random_bytes()and random_int()for PHP 5 projects.
如果您还没有使用 PHP 7(可能是这种情况,因为在撰写本文时它还没有发布),那么您将需要paragonie/random_compat,它是PHP 5 项目的用户空间实现random_bytes()和random_int()用于 PHP 5 项目。
For security contexts, alwaysuse random_int(), not rand(), mt_rand(), etc.See ircmaxell's answeras well.
出于安全环境中,总是使用random_int(),不rand(),mt_rand()等见ircmaxell的回答也是如此。

