ChatGPT解决这个技术问题 Extra ChatGPT

PHP 随机字符串生成器

我正在尝试在 PHP 中创建一个随机字符串,但我绝对没有输出:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;

我究竟做错了什么?

我生成短字符串的单行解决方案是 substr(md5(rand()), 0, 7);祝你好运 ...
@tasmaniski ..您的解决方案还可以..但随机性较低!在您的示例中,可以生成的随机字符串的数量受整数大小的限制。 ( 2^32 ) 最大.. 如果是其他解决方案,您可以生成 ( 62^8 ).. 如果我想要更大的字符串,那么不同字符串的数量保持在最大 2^32,但在其他解决方案它增加到( 62^n )..
您忘记将每个新生成的字符添加到字符串中。您只是按原样覆盖它。应该是 $randstring .= $characters..
@CaptainLightning 您能否将接受的答案换成更安全的答案之一? :)
strlen($characters) => strlen($characters) - 1 - 字符串长度从 1 开始

s
steadweb

要具体回答这个问题,有两个问题:

当您回显它时,$randstring 不在范围内。字符没有在循环中连接在一起。

这是一个带有更正的代码片段:

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

使用以下调用输出随机字符串:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

请注意,这会生成可预测的随机字符串。如果要创建安全令牌,请参阅此答案。


@FranciscoPresencia,在循环的比较条件中调用方法时,最好“浪费”一个额外的变量。
所有这些工作,为什么不只是像 substr(str_shuffle(MD5(microtime())), 0, 10); 之类的东西?
感谢您提供代码,但请将 rand() 更改为 mt_rand()。我使用了您的方法并经历了 ton 与名称的冲突。
@FranciscoPresencia 你知道那是多么低效吗?您每次迭代都会检查两次字符串的长度!循环内的 strlen 也应该在进入循环之前缓存在一个变量中。
这不是一个好的解决方案。这生成的字符串将是可预测的。 :(
C
Community

注意:str_shuffle() 内部使用了 rand(),这不适合加密目的(例如生成随机密码)。您需要一个安全的随机数生成器。它也不允许字符重复。

还有一种方法。

更新(现在这会生成任意长度的字符串):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)

而已。 :)


+1 最短答案:)。但不是每个用例的最佳答案。此代码将输出字符串,其中每个字符不会出现多次(从而使其更弱于暴力攻击),并且不会输出任何超过 62 个字符的内容。
不要这样做,它非常弱。你制作的随机字符串越长,它就越弱。
它可能很弱,但它又快又容易。根据用例,这很好——我使用它是因为我不需要安全性或强度;只是一个快速的洗牌。我正在编写一个单元测试,这给了我一个适当的随机输入来测试。
@FranciscoPresencia 它不安全的原因是它从不使用相同的字符两次。这使它成为一个糟糕的密码生成器。请大家停止投票,绝对不安全,绝对不能使用。随着密码变长,您必须在蛮力中测试的字符数会变短,因为您不必费心测试任何以前使用过的字符。
@FranciscoPresencia:我支持您关于避免将其用于随机密码的评论。但是,我不同意这个答案不应该加一。我有这个选项,因为它是生成随机字符串的有效单行解决方案(这个问题的原始主题)。
S
Scott Arciszewski

这个问题有很多答案,但没有一个利用 Cryptographically Secure Pseudo-Random Number Generator (CSPRNG)。

简单、安全且正确的答案是使用 RandomLib 而不要重新发明轮子。

对于那些坚持发明自己的解决方案的人,PHP 7.0.0 将为此提供 random_int();如果您仍在使用 PHP 5.x,我们编写了一个 PHP 5 polyfill for random_int(),以便您甚至可以在升级到 PHP 7 之前使用新的 API。

Safely generating random integers in PHP 不是一项简单的任务。在生产中部署本地算法之前,您应该始终检查 your resident StackExchange cryptography experts

有了安全的整数生成器,使用 CSPRNG 生成随机字符串就像在公园里散步一样。

创建一个安全的随机字符串

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * For PHP 7, random_int is a PHP core function
 * For PHP 5.x, depends on https://github.com/paragonie/random_compat
 * 
 * @param int $length      How many characters do we want?
 * @param string $keyspace A string of all possible characters
 *                         to select from
 * @return string
 */
function random_str(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}

用法:

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();

Demohttps://3v4l.org/IMJGF(忽略 PHP 5 故障;它需要 random_compat)


在函数开头添加 $keyspace = str_shuffle($keyspace ); 以提高安全性
“为了更安全”是什么意思?我们已经在使用安全的随机数生成器。
@JGEstiot 创建安全的随机字符串需要密码安全的随机性。搜索“如何在 PHP 中生成随机字符串”的人最好使用安全答案而不是不安全答案。
@ Scott Arciszewski 您不需要在每次创建随机字符串时都创建加密随机字符串。问题是关于创建随机字符串,这与安全性无关。您假设该字符串将在安全敏感的上下文中使用,并且您添加了一层复杂性以阻止问题的核心。
使用 random_int() 而不是 rand()mt_rand() 不会增加开发人员的复杂性。同时,它给了他们更大的安全感。来 StackOverflow 寻找快速解决方案的人可能不知道他们正在构建的东西是否需要安全。如果我们给他们默认的安全答案,他们会创建一个更安全的互联网,即使从他们的角度来看,这完全是偶然的。为什么你会反对这个目标对我来说是个谜。
P
Peter Mortensen

这将创建一个 20 个字符长的十六进制字符串:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

在 PHP 7 (random_bytes()) 中:

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f

请注意,openssl_random_pseudo_bytes() 直到 php 5.6 才使用加密强算法。相关错误:bugs.php.net/bug.php?id=70014
另请注意,这可以生成的最小字符串的长度为 2。如果您将 1 或更少的字节长度传递给 openssl_random_pseudo_bytes(),您将一无所获。另外,请注意,当使用 bin2hex(openssl_random_pseudo_bytes($length / 2)) 时,因为您使用的是整数,它会自动删除模数并使用 2 的下一个最小倍数。因此,$length = 19 将生成长度为 18 的字符串。
建议将其用作可以通过 fgets($fp, 1024) 打开的文件内容以及每个存在超长行问题的文件编辑器:function string_rand($len, $split="\n") { return substr(chunk_split(bin2hex(openssl_random_pseudo_bytes(ceil($len / 2))), 1023, $split), 0, $len); } 如果应该返回单行,请将 $split 设置为 null。这样你就可以在这两种情况下使用它。
我真的很喜欢 PHP 7 的 random_bytes 解决方案,但是如果你需要字符串是一定数量的字符,这样的工作会怎样? $string = substr(base64_encode(random_bytes($size)), 0, $size);
这绝对是最好的解决方案。占用空间很小,而且非常容易理解。
H
Humphrey

@tasmaniski:你的回答对我有用。我有同样的问题,我会建议那些一直在寻找相同答案的人。这是来自@tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>

这是一个youtube video showing us how to create a random number


如果您的字符串仅基于随机整数,为什么不使用随机整数?他们干草堆并没有通过散列而变得更深......并且通过削减你的散列实际上消除了你必须开始的小熵。
请记住,md5 将导致 30 个字符的限制,并且始终为小写字符。
此外,rand() 不应用于加密。如果您希望生成一个加密的声音字符串,请使用 openssl_random_pseudo_bytes
md5(rand()) 仅提供 2^32 个可能的值。这意味着平均而言,在 2^16 个随机字符串之后,您会期望其中一个重复。
好吧..我敢打赌,OP 不是在谈论“安全随机字符串”。对于正确的用例,该解决方案紧凑、简单且易于记忆。而且,如果您需要处理可能的冲突,为什么不在随机字符串前面/附加时间戳? :)
r
rjmunro

根据您的应用程序(我想生成密码),您可以使用

$string = base64_encode(openssl_random_pseudo_bytes(30));

作为 base64,它们可能包含 =- 以及请求的字符。您可以生成更长的字符串,然后对其进行过滤和修剪以删除它们。

openssl_random_pseudo_bytes 似乎是在 php.ini 中生成正确随机数的推荐方式。为什么 rand 不使用 /dev/random 我不知道。


rand 不使用 /dev/urandom 因为它仅在类似 posix 的环境中可用并且不可移植。
@MacroMan 但是openssl_random_pseudo_bytes() 可移植的。
如果你想去掉多余的 base64 字符,试试这个:gist.github.com/zyphlar/7217f566fc83a9633959
这没有错,但我建议您在丢弃不需要的字符时要谨慎。例如,参见 this pull request on the PHP league's OAuth2 Server
这是最好的答案之一。可惜没有更多的支持。我建议您编辑您的答案,以便更好地处理不需要的字符。
M
Madan Sapkota

PHP 7+ 使用 random_bytes 函数生成加密安全的随机字节。

$bytes = random_bytes(16);
echo bin2hex($bytes);

可能的输出

da821217e61e33ed4b2dd96f8439056c

PHP 5.3+ 使用 openssl_random_pseudo_bytes 函数生成伪随机字节。

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);

可能的输出

e2d1254506fbb6cd842cd640333214ad

最好的用例可能是

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();

可能的输出

ba8cc342bdf91143


这不会生成具有给定长度的字符串
getRandomBytes() (所有这些,真的)只适用于偶数长度。除此之外,这里是更好、不那么可怕的答案之一。
@DewiMorgan,我猜任何散列算法都会产生均匀的长度。
好吧,更多的是 bin2hex() 将不可避免地返回偶数个十六进制字符。据我所知,对于奇数长度的情况,将输出截断一个字符不应该影响熵......但我承认它会在代码中添加一些额外的行,这对几乎所有使用都毫无意义-案例。
所以 $odd=$length%2; $长度+=$奇数;在开头,并返回 substr(bin2hex($length), $odd);最后会成功......但代价是相当大的可读性。你的更干净,更易于维护,所以如果我要使用它,我可能会添加一个关于“只有偶数长度”警告的评论,除非它真的很重要。
P
Peter Mortensen

这是一个简单的单行程序,它可以生成真正的随机字符串,而无需任何脚本级别的循环或使用 OpenSSL 库。

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);

分解它以便参数清晰

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);

此方法通过随机重复字符列表来工作,然后打乱组合字符串,并返回指定的字符数。

您可以进一步随机化,方法是随机化返回字符串的长度,将 $chrRandomLength 替换为 mt_rand(8, 15)(对于 8 到 15 个字符之间的随机字符串)。


很抱歉,但是当一个角色被选中时,它再次出现的概率并不像池中的其他角色那么高。这里没有真正的随机性......
@TheSurrican - 你在那个陈述中是不正确的。使用此算法,所有字符具有相同的概率,因此是真正随机的。这是通过重复 chrList 字符串 $chrRepeatMax 来确保的,而魔法确实发生在 str_shuffle 中,它决定了随机性。
这个算法很聪明,但它是基于 mt_rand,它生成一个确定的数字序列。输出可以通过获取或猜测盐来解码。在任何条件下,一个真正的随机序列都不能被解码为熵较小的东西,比如一个小整数。一些系统通过测量一个人打字或移动鼠标需要多长时间来生成真实世界的熵,从而实现了对真实随机性的良好近似。请注意,使用系统时间也不是真正随机的,因为攻击者有时可以拦截设备计时信号。
str_shuffle 是确定性的,而不是真正随机的。
投反对票的原因:1)当 mt_rand 不是真正随机时,声称“真正的随机字符串”而不是“伪随机字符串”;声称字符选择的概率相等,这表明对统计数据的误解。一旦从字符串中选择了第一个字符,则选择第二个字符的概率为 9/(10*n),而所有其他字符为 10/(10*n)。这个东西很重要:这样的错误在安全环境中是危险的。
P
Peter Mortensen

实现此功能的更好方法是:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);

根据 PHP 7 中的 thisthismt_rand 更加随机。 rand 函数是 mt_rand 的别名。


注意:mt_rand 不会生成加密安全值。为此,您应该使用 PHP7 的 random_intrandom_bytes
D
Davor
function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}

多田!


请记住,sha1 将导致 40 个字符的限制,并且始终为小写字符。
sha1 字符串不是随机的,某些字符会比其他字符更频繁地出现。在您真正想要随机性(例如密码)的情况下使用它是不明智的。
@KitSunde - 是的, sha 不是随机的, rand() 是随机的。 sha 非常适合这里需要的东西。 OP 不需要加密级别的随机性。
当 sha 分布不均匀时,@Davor rant() 随机无关紧要。如果您从不均匀分布中随机选择,您将得到完全相同的不均匀分布。我要强调的不是“加密级别”随机性,如果是这种情况,您也不应该使用 rand()。像在接受的答案中那样从均匀分布中提取需要最少的努力,并且它与 rand() 一样随机,这是合理的。
@KitSunde - 它最终没有任何区别。这正是过度工程和镀金的定义。
B
BoltClock

函数作用域中的 $randstring 与调用它的作用域不同。您必须将返回值分配给变量。

$randstring = RandomString();
echo $randstring;

或者直接回显返回值:

echo RandomString();

另外,在你的函数中你有一个小错误。在 for 循环中,您需要使用 .= 以便将每个字符附加到字符串中。通过使用 =,您将用每个新字符覆盖它,而不是追加。

$randstring .= $characters[rand(0, strlen($characters))];

4
4 revs

首先,您定义要使用的字母表:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;

然后,使用 openssl_random_pseudo_bytes() 生成正确的随机数据:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);

最后,您使用此随机数据创建密码。由于 $random 中的每个字符在 chr(255) 之前都可以是 chr(0),因此代码使用将其序数值除以 $alphabet_length 后的余数来确保只选择字母表中的字符(请注意,这样做会使随机性产生偏差):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}

或者,通常更好的是使用 RandomLibSecurityLib

use SecurityLib\Strength;

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new Strength(Strength::MEDIUM));

$password = $generator->generateString(12, $alphabet);

使用模运算符 % 将产生有偏差的输出。但是,对于 RandomLib,强 +1。不要重新发明轮子。
是的,新的 random_int() 函数很好:D
P
Putnik

我在那里测试了最流行函数的性能,在我的盒子上生成 1'000'000 个 32 个符号的字符串所需的时间是:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);

请注意,它实际上有多长并不重要,但哪个更慢,哪个更快,因此您可以根据您的要求进行选择,包括加密准备等。

如果您需要短于 32 个符号的字符串,则添加了 MD5 周围的 substr() 以确保准确性。

为了回答:字符串没有被连接而是被覆盖,并且函数的结果没有被存储。


我想,最好的答案。谢谢!
r
rAthus

这是我生成使用友好的随机密码的简单单行解决方案,不包括“1”和“l”、“O”和“0”等看起来相似的字符……这里是 5 个字符,但你可以轻松当然改变它:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);

这非常适合创建随机 ID 字符串以便稍后在 jquery 上调用。 IDK,如果它是好的做法,但这对我有很大帮助,而不是像公认的答案那样使用...
这种方法比您最初预期的要“不那么随机”,因为任何字符都不会被多次使用。
你是对的@Deji,一个五个字符长度的字符串将“仅”有 3.79 亿个可能的组合,而不是 4.59 亿个。
实际上,您的 5 字符子字符串可以生成不到 3.12 亿个排列。老实说,我不确定如何计算后者。
@Deji 你是怎么达到 312M 的?歌曲从 54 个字符中第一个开始,然后从其余的字符开始,依此类推,五次,即 54*53*52*51*50 = 379.501.200 种可能的组合。
P
Punit Gajjar

简短的方法..

这是生成随机字符串的一些最短方法

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

echo substr(md5(rand()), 0, 7);

echo str_shuffle(MD5(microtime()));
?>

B
BassMHL

一种非常快速的方法是执行以下操作:

substr(md5(rand()),0,10);

这将生成一个长度为 10 个字符的随机字符串。当然,有些人可能会说它在计算方面有点重,但现在处理器已经过优化,可以非常快速地运行 md5 或 sha256 算法。当然,如果 rand() 函数返回相同的值,结果将是相同的,有 1 / 32767 的机会相同。如果安全是问题,那么只需将 rand() 更改为 mt_rand()


a
artnikpro

Laravel 5 框架的辅助函数

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}

“对于密码学等来说,不应该被认为是足够的。”应该强烈强调这一点。
M
Mr. Coderx
function gen_uid($l=5){
   return substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"), 10, $l);
}
echo gen_uid();

默认值[5]:WvPJz

echo gen_uid(30);

值[30]:cAiGgtf1lDpFWoVwjykNKXxv6SC4Q2


V
Vasil Kulakov

从 php7 开始,就有了 random_bytes 函数。 https://www.php.net/manual/ru/function.random-bytes.php 这样您就可以生成一个随机字符串

<?php
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));
?>

Р
Руслан Ибрагимов
function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}

这不是便携式的;如果您尝试在任何非 posix 环境中运行它,将导致致命错误。
u
userlond

这个取自 adminer sources

/** Get a random string
* @return string 32 hexadecimal characters
*/
function rand_string() {
    return md5(uniqid(mt_rand(), true));
}

Adminer,用 PHP 编写的数据库管理工具。


s
sxn

来自 yii2 框架

/**
 * Generates a random string of specified length.
 * The string generated matches [A-Za-z0-9_-]+ and is transparent to URL-encoding.
 *
 * @param int $length the length of the key in characters
 * @return string the generated random key
 */

function generateRandomString($length = 10) {
    $bytes = random_bytes($length);
    return substr(strtr(base64_encode($bytes), '+/', '-_'), 0, $length);
}

好的解决方案我使用相同的技术以不同的方式制作了这个谢谢你的伙伴
适用于我需要实现的目标,非常感谢
m
mike_t
/**
 * @param int $length
 * @param string $abc
 * @return string
 */
function generateRandomString($length = 10, $abc = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
{
    return substr(str_shuffle($abc), 0, $length);
}

来源来自 http://www.xeweb.net/2011/02/11/generate-a-random-string-a-z-0-9-in-php/


P
Peter Mortensen

另一个单行,它生成包含字母和数字的 10 个字符的随机字符串。它将创建一个带有 range 的数组(调整第二个参数以设置大小),循环该数组并分配一个随机 ASCII 字符(范围 0-9 或 az),然后将数组内爆以获得一个字符串。

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));

注意:这只适用于 PHP 5.3 及更高版本


最后是一个真正随机的解决方案,而不是 32 位随机整数或洗牌字符串的一些臃肿散列......
只有一个问题:数字和字符一样可能出现,这不像我想要的那样随机。无论如何 +1 以获得此页面上的最佳解决方案。调整它和它的完美。
调整……像这样? rand(0, 57-48+122-97)<57-48?...:... ? :)
P
Peter Mortensen

一个班轮。

对于具有某些独特性的大字符串来说,它的速度很快。

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}

md5(rand()) 是一种非常不安全的随机数生成方式。
一个具有 X 长度和一些唯一性的字符串是意图。真正的随机性不是意图。
P
Peter Mortensen
function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}

P
Peter Mortensen

该函数的编辑版本工作正常,但我发现只有一个问题:您使用了错误的字符来括住 $characters,因此 ' 字符有时是生成的随机字符串的一部分。

要解决此问题,请更改:

$characters = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

至:

$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

这种方式只使用封闭的字符,并且 ' 字符永远不会成为生成的随机字符串的一部分。


M
MRMP
function generateRandomString($length = 10, $hasNumber = true, $hasLowercase = true, $hasUppercase = true): string
{
    $string = '';
    if ($hasNumber)
        $string .= '0123456789';
    if ($hasLowercase)
        $string .= 'abcdefghijklmnopqrstuvwxyz';
    if ($hasUppercase)
        $string .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return substr(str_shuffle(str_repeat($x = $string, ceil($length / strlen($x)))), 1, $length);
}

并使用:

echo generateRandomString(32);

R
RKaneKnight

我喜欢使用 openssl_random_pseudo_bytes 的最后一条评论,但这对我来说不是一个解决方案,因为我仍然必须删除我不想要的字符,而且我无法获得设定长度的字符串。这是我的解决方案...

function rndStr($len = 20) {
    $rnd='';
    for($i=0;$i<$len;$i++) {
        do {
            $byte = openssl_random_pseudo_bytes(1);
            $asc = chr(base_convert(substr(bin2hex($byte),0,2),16,10));
        } while(!ctype_alnum($asc));
        $rnd .= $asc;
    }
    return $rnd;
}

J
James McCracken

这是我如何获得真正唯一的随机密钥:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;

您可以使用 time() 因为它是一个 Unix 时间戳,并且与上面提到的其他随机相比始终是唯一的。然后,您可以生成它的 md5sum 并从生成的 MD5 字符串中获取所需的长度。在这种情况下,我使用 10 个字符,如果我想让它更独特,我可以使用更长的字符串。

我希望这有帮助。


当然,time() 远非唯一:它会一次又一次地返回相同的值,直到当前秒结束。这里真正提供了一些随机性的是 str_shuffle()——其余的代码只减少了从中挑选字符的样本。
所以你基本上在做的是围绕一个 32 位整数洗牌。这里没有很多熵...
攻击者可以猜测 time() 返回的值(它只是一个时间戳),它是一个弱随机源。