在php中生成随机密码

Posted

技术标签:

【中文标题】在php中生成随机密码【英文标题】:Generating a random password in php 【发布时间】:2011-08-31 09:53:03 【问题描述】:

我正在尝试在 php.ini 中生成一个随机密码。

但是我得到了所有的'a'并且返回类型是数组类型,我希望它是一个字符串。关于如何更正代码的任何想法?

谢谢。

function randomPassword() 
    $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
    for ($i = 0; $i < 8; $i++) 
        $n = rand(0, count($alphabet)-1);
        $pass[$i] = $alphabet[$n];
    
    return $pass;

【问题讨论】:

没有一个答案使用secure random number generator,你想用它作为密码。 访问者应该从可以正确更新的来源获得潜在的安全相关信息,而不是对新答案封闭的问题。我将删除此副本的答案,以便访问者改为阅读未解决问题的答案。 (如果这个问题被重新打开,答案将不会被删除。) @JeremyBanks 问题没有说明需要加密安全密码。对于某些人来说,使用 /dev/random 的答案就足够了,因为该问题不要求输入“secure”密码(并且不应编辑以包含该密码,因为它会改变原始问题)。虽然我完全是为了安全,但我认为这个地毯炸弹并没有被充分考虑。与使用mysql_* 一样,答案仍然有效,但应标记为不安全。也许这是 SO 需要作为额外软件包含的东西 - 警告不安全代码的能力? @JeremyBanks 你能恢复这个问题的答案吗?仅仅因为它是重复的,并不意味着答案是错误的(我不小心投票重新打开,我同意它是重复的)。删除答案是没有意义的,请考虑删除这个问题并将答案迁移到另一个问题(我以前见过它)。 @JeremyBanks 如果您不想重新打开某些内容,请将其锁定。否则 99% 的人会重新打开它并造成一团糟。就我个人而言,我完全不同意像这样删除高分答案,但不能为此与您抗衡 【参考方案1】:

安全警告rand() 不是加密安全的伪随机数生成器。在别处寻找generating a cryptographically secure pseudorandom string in PHP。

试试这个(使用strlen而不是count,因为字符串上的count总是1):

function randomPassword() 
    $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    $pass = array(); //remember to declare $pass as an array
    $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
    for ($i = 0; $i < 8; $i++) 
        $n = rand(0, $alphaLength);
        $pass[] = $alphabet[$n];
    
    return implode($pass); //turn the array into a string

Demo

【讨论】:

使用$pass .= $alphabet[$n]似乎更直接。 使用 rand 生成 password 是一个非常糟糕的主意。这不是一个安全的 PRNG。 (没有mt_rand 也不是更好) 问题是关于生成密码。生成密码的代码显然需要使用安全的随机数。 出于与这不是重复问题相同的原因,这个答案是不正确的,因为问题是关于生成密码不是 随机字符串。这个答案提供了一种非常不安全的方法来生成密码。请在下面使用@user3260409 的答案,其中使用openssl_random_pseudo_bytes() 而不是rand() 我已经看到您的不安全代码在生产中,并希望从源头上阻止它。您需要对密码的随机性进行加密保护。【参考方案2】:

TL;DR:

使用random_int() 和下面给定的random_str()。 如果您没有random_int(),请使用random_compat。

说明:

由于您正在生成 密码,因此您需要确保您生成的密码是不可预测的,并且确保此属性存在于您的实现中的唯一方法是使用 cryptographically secure pseudorandom number generator ( CSPRNG)。

对于随机字符串的一般情况,可以放宽对 CSPRNG 的要求,但在涉及安全性时则不能。

在 PHP 中生成密码的简单、安全和正确的答案是使用RandomLib,而不是重新发明***。这个库已经过行业安全专家以及我自己的审核。

对于喜欢发明自己的解决方案的开发人员,PHP 7.0.0 将为此提供random_int()。如果您仍在使用 PHP 5.x,我们写了一个PHP 5 polyfill for random_int(),以便您可以在 PHP 7 发布之前使用新的 API。使用我们的random_int() polyfill可能比编写自己的实现更安全。

手头有一个安全的随机整数生成器,生成一个安全的随机字符串比饼图更容易:

<?php
/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 * 
 * 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(
    $length,
    $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
) 
    $str = '';
    $max = mb_strlen($keyspace, '8bit') - 1;
    if ($max < 1) 
        throw new Exception('$keyspace must be at least two characters long');
    
    for ($i = 0; $i < $length; ++$i) 
        $str .= $keyspace[random_int(0, $max)];
    
    return $str;

【讨论】:

RandomLib 已经两年多没有更新了。在最近的 PHP 构建(在我的例子中是 7.1.25)上使用它会引发各种 mcrypt_* 函数的弃用警告。我可以在an issue thread 上看到您拥有forked the library,因为无法获得@ircmaxell,但是您的fork 在 Travis 上说“构建失败”。您是否愿意更新这个答案(在 Google 上仍然显示很高)? 好收获!它需要被删除。【参考方案3】:

我知道您正在尝试以特定方式生成密码,但您可能也想查看此方法...

$bytes = openssl_random_pseudo_bytes(2);

$pwd = bin2hex($bytes);

它取自 php.net 站点,它创建的字符串长度是您在 openssl_random_pseudo_bytes 函数中输入的数字的两倍。所以上面会创建一个长度为 4 个字符的密码。

总之……

$pwd = bin2hex(openssl_random_pseudo_bytes(4));

将创建一个长度为 8 个字符的密码。

但请注意,密码仅包含数字 0-9 和小写字母 a-f!

【讨论】:

如果你想要一个大写、小写和数字的密码,试试这个:gist.github.com/zyphlar/7217f566fc83a9633959 @زياد 说谁?如果生成器使用 7 位字节,我会同意你的看法,但 openssl_random_pseudo_bytes() 是一个强大的全二进制字节随机生成器,不需要任何进一步的改组。此外,我将借此机会指出,假设堆叠多种加密方法会使任何事情变得更加随机是很危险的,在某些情况下,由于累积的散列冲突,实际上可能正好相反。【参考方案4】:

2 行的小代码。

演示:http://codepad.org/5rHMHwnH

function rand_string( $length ) 

    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return substr(str_shuffle($chars),0,$length);



echo rand_string(8);

您可以使用 rand_string 定义将创建多少字符。

【讨论】:

很好,尽管使用这种方法不会得到任何重复的字符,这可能是不可取的。 这个函数对于生成长密码很糟糕。首先,如果 $length 比 $chars 字符串长,那么您将不会收到与您输入的长度一样长的字符串,而是 chars 字符串的长度。此外,您只能保证每个字符中只有 1 个没有重复。它也不保证使用大写字母或数字,这通常是必需的(当然,除非您的长度由于先前的错误而超过 26) 这个@Programster 和@Hobo 怎么样? substr(str_shuffle(str_repeat($chars,$length)),0,$length); @Charles-EdouardCoste 似乎工作得很好(特别是如果你加入一些特殊的字符)。尽管它仍然不保证每种字符类型中的至少一种。唯一困扰我的是通过所需密码的长度重复整个字符集,但这确保生成的密码中的字符不必是唯一的,并且在一次使用中不会对性能产生明显的影响。 我同意。最好不要根据行数选择算法。顺便说一句,如果主要目标只是在网站上创建新用户时生成一个临时密码,我想这可以满足需求。【参考方案5】:

如果您使用的是 PHP7,则可以使用 random_int() 函数:

function generate_password($length = 20)
  $chars =  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
            '0123456789`-=~!@#$%^&*()_+,./<>?;:[]\|';

  $str = '';
  $max = strlen($chars) - 1;

  for ($i=0; $i < $length; $i++)
    $str .= $chars[random_int(0, $max)];

  return $str;

下面的旧答案:

function generate_password($length = 20)
  $chars =  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
            '0123456789`-=~!@#$%^&*()_+,./<>?;:[]\|';

  $str = '';
  $max = strlen($chars) - 1;

  for ($i=0; $i < $length; $i++)
    $str .= $chars[mt_rand(0, $max)];

  return $str;

【讨论】:

不要使用mt_rand生成密码。 @CodesInChaos 它比上面示例使用的 rand() 更好。根据 PHP 手册,首选 openssl_random_pseudo_bytes()。 @willbradley 种子的质量与mt_rand 一样糟糕,因此它仍然不适合任何安全用途。 你看这就是让我烦恼的 +ChaosInCodes。你没有看过这个问题,你只是做了一些笼统的陈述,重复了一堆不正确的信念。简而言之:针对完全不同的问题的正确建议。随机密码很好。它们可能仅用于“x”。老实说,如果您设计的系统没有定时锁定和 DOS 检测以及“x 尝试然后 -> 锁定”,那么您做错了。在采取此类措施的情况下,猜测 mt_rand 密码是不可能的。相反,使用 mt_rand 不会更容易暴力破解密码。它只是不会。 我不会在$chars中使用\【参考方案6】:

一行:

substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )

【讨论】:

这可以防止重复使用相同的字母,因为它们只是随机播放但不会出现多次。 不用说,没有人应该根据行数优化他们的密码生成功能。即使使用的 RNG 是安全的(它不是),在生成 10 个字符的密码时避免重复字符也会使您的熵从约 52 位降至约 50 位(破解速度快约 4 倍)。如果将其扩展到 20 个字符,则不重复将使您从 ~103 位降至 ~94 位(破​​解速度快 ~512 倍)。 这个方法让我想起了flaw in the Enigma codelol substr(str_shuffle(str_repeat($chars,$length)),0,$length);熵恢复【参考方案7】:

您最好的选择是RandomLib library by ircmaxell

使用示例:

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

$passwordLength = 8; // Or more
$randomPassword = $generator->generateString($passwordLength);

它生成的字符串比shuffle()rand() 之类的普通随机函数更具有随机性(对于密码、盐和密钥等敏感信息,您通常需要这些函数)。

【讨论】:

这是正确答案。不要使用rand()mt_rand() 这可能是最安全的答案(不确定它与random_bytes 相比如何),但这并不意味着rand 的答案不正确。 rand is not a good choice for passwords @Cerbrus:当然这个答案并没有使使用rand() 的答案不正确。它们本身就是不正确的!【参考方案8】:

我将发布一个答案,因为一些现有答案很接近,但有一个:

比您想要的更小的字符空间,以便暴力破解更容易,或者密码必须更长才能获得相同的熵 RNG 不被视为加密安全 对某些 3rd 方库的要求,我认为展示自己可能需要做的事情可能会很有趣

这个答案将绕过count/strlen 问题,因为生成的密码的安全性,至少恕我直言,超越了你如何到达那里。我还将假设 PHP > 5.3.0。

让我们把问题分解成几个组成部分:

    使用一些安全的随机源来获取随机数据 使用该数据并将其表示为一些可打印的字符串

对于第一部分,PHP > 5.3.0 提供了函数openssl_random_pseudo_bytes。请注意,虽然大多数系统使用加密强算法,但您必须进行检查,以便我们使用包装器:

/**
 * @param int $length
 */
function strong_random_bytes($length)

    $strong = false; // Flag for whether a strong algorithm was used
    $bytes = openssl_random_pseudo_bytes($length, $strong);

    if ( ! $strong)
    
        // System did not use a cryptographically strong algorithm 
        throw new Exception('Strong algorithm not available for PRNG.');
            

    return $bytes;

对于第二部分,我们将使用base64_encode,因为它需要一个字节字符串,并且会生成一系列字符,其字母表与原始问题中指定的字母表非常接近。如果我们不介意在最终字符串中出现+/= 字符,并且我们希望结果至少有$n 个字符长,我们可以简单地使用:

base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4))));

3/4 因素是由于 base64 编码产生的字符串长度至少比字节字符串大三分之一。对于$n,结果将是精确的,它是 4 的倍数,否则最多长 3 个字符。由于额外的字符主要是填充字符=,如果我们出于某种原因限制密码的长度是精确的,那么我们可以将其截断为我们想要的长度。这尤其是因为对于给定的 $n,所有密码都将以相同数量的密码结尾,因此有权访问结果密码的攻击者最多可以少 2 个字符来猜测。


为了获得额外的荣誉,如果我们想要满足 OP 问题中的确切规范,那么我们将不得不做更多的工作。我将在这里放弃基本转换方法,并采用一种快速而肮脏的方法。由于 62 个条目的长字母表,两者都需要产生比结果中使用的更多的随机性。

对于结果中多余的字符,我们可以简单地将它们从结果字符串中丢弃。如果我们从字节字符串中的 8 个字节开始,那么大约 25% 的 base64 字符将是这些“不受欢迎的”字符,因此简单地丢弃这些字符会产生一个不短于 OP 所需的字符串。然后我们可以简单地截断它以得到确切的长度:

$dirty_pass = base64_encode(strong_random_bytes(8)));
$pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8);

如果您生成更长的密码,填充字符 = 在中间结果中的比例会越来越小,这样您就可以实施更精简的方法,前提是要考虑耗尽用于 PRNG 的熵池。

【讨论】:

感谢您的加入。现有答案均未指出 openssl_random_pseudo_bytes 可能会产生较弱的结果。我没有意识到是这样的。【参考方案9】:

你想要strlen($alphabet),而不是常量alphabet(相当于'alphabet')的count

但是,rand 不是用于此目的的合适随机函数。它的输出可以很容易地预测,因为它是隐含在当前时间播种的。此外,rand 不是加密安全的;因此,从输出中确定其内部状态相对容易。

相反,从/dev/urandom 读取以获取加密随机数据。

【讨论】:

【参考方案10】:

base_convert(uniqid('pass', true), 10, 36);

例如。 e0m6ngefmj4

编辑

正如我在 cmets 中提到的,长度意味着蛮力攻击比定时攻击更有效,因此不必担心“随机生成器的安全性”。安全性,特别是对于这个用例,需要补充可用性,因此上述解决方案实际上足以解决所需的问题。

但是,以防万一您在搜索安全的随机字符串生成器时偶然发现了这个答案(我假设有些人基于响应),对于诸如生成令牌之类的东西,以下是此类代码生成器的方式看起来像:

function base64urlEncode($data) 
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');


function secureId($length = 32) 

    if (function_exists('openssl_random_pseudo_bytes')) 
        $bytes = openssl_random_pseudo_bytes($length);
        return rtrim(strtr(base64_encode($bytes), '+/', '0a'), '=');
    
    else  // fallback to system bytes

        error_log("Missing support for openssl_random_pseudo_bytes");

        $pr_bits = '';

        $fp = @fopen('/dev/urandom', 'rb');
        if ($fp !== false) 
            $pr_bits .= @fread($fp, $length);
            @fclose($fp);
        

        if (strlen($pr_bits) < $length) 
            error_log('unable to read /dev/urandom');
            throw new \Exception('unable to read /dev/urandom');
        

        return base64urlEncode($pr_bits);
    

【讨论】:

PS - 这是 PHP - 只是使用 \ 来表示全局命名空间。 除了 uniqid 不是加密安全的。使用 rand() 代替:base_convert(rand(78364164096, 2821109907455), 10, 36); 根据 PHP 手册,@Benubird rand() 也不是加密安全的。手册建议改为 openssl_random_pseudo_bytes()。 对于大多数用例,特别是在攻击者无法访问确切时间的情况下,这完全没问题,并且会产生一个或多或少对人类友好的“临时”密码。如果我们把这个发挥到极致,这里的长度就麻烦多了,那么用什么函数来生成随机数。 我为感兴趣的人添加了一个生成完全安全字符串的示例;但强烈建议不要在为用户生成临时密码时使用它。即使使用安全版本,长度问题仍然存在。【参考方案11】:

变得更聪明一点:

function strand($length)
  if($length > 0)
    return chr(rand(33, 126)) . strand($length - 1);

检查here。

【讨论】:

【参考方案12】:

另一个(仅限 Linux)

function randompassword()

    $fp = fopen ("/dev/urandom", 'r');
    if (!$fp)  die ("Can't access /dev/urandom to get random data. Aborting."); 
    $random = fread ($fp, 1024); # 1024 bytes should be enough
    fclose ($fp);
    return trim (base64_encode ( md5 ($random, true)), "=");

【讨论】:

读取 1024 字节压缩成 128 位的熵加密散列有点浪费。此外,fread() 默认缓冲为 8192 字节,因此您总是会使用给定的代码从/dev/urandom 读取那么多字节。这也不适用于 Windows。不过,感谢使用 CSPRNG。【参考方案13】:

尝试使用大写字母、小写字母、数字和特殊字符

function generatePassword($_len) 

    $_alphaSmall = 'abcdefghijklmnopqrstuvwxyz';            // small letters
    $_alphaCaps  = strtoupper($_alphaSmall);                // CAPITAL LETTERS
    $_numerics   = '1234567890';                            // numerics
    $_specialChars = '`~!@#$%^&*()-_=+][;:,<.>/?\'"\|';   // Special Characters

    $_container = $_alphaSmall.$_alphaCaps.$_numerics.$_specialChars;   // Contains all characters
    $password = '';         // will contain the desired pass

    for($i = 0; $i < $_len; $i++)                                  // Loop till the length mentioned
        $_rand = rand(0, strlen($_container) - 1);                  // Get Randomized Length
        $password .= substr($_container, $_rand, 1);                // returns part of the string [ high tensile strength ;) ] 
    

    return $password;       // Returns the generated Pass

假设我们需要 10 位通行证

echo generatePassword(10);  

示例输出:

,IZCQ_IV\7

@wlqsfhT(d

1!8+1\4@uD

【讨论】:

rand 函数实际上在密码学上并不安全,因此使用它生成密码可能会有很大风险【参考方案14】:

使用这个简单的代码生成 12 长的中等强度密码

$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);

【讨论】:

这实际上是(非常?)错误的。它实际上只使用字母表中的每个字符一次,因此严重缩小了所有可能值的空间(与破解相关)。【参考方案15】:

快一。简单、干净和一致的格式,如果你想要的话

$pw = chr(mt_rand(97,122)).mt_rand(0,9).chr(mt_rand(97,122)).mt_rand(10,99).chr(mt_rand(97,122)).mt_rand(100,999);

【讨论】:

【参考方案16】:

这是基于此页面上的另一个答案,https://***.com/a/21498316/525649

这个答案只生成十六进制字符0-9,a-f。对于看起来不像十六进制的东西,试试这个:

str_shuffle(
  rtrim(
    base64_encode(bin2hex(openssl_random_pseudo_bytes(5))),
    '='
  ). 
  strtoupper(bin2hex(openssl_random_pseudo_bytes(7))).
  bin2hex(openssl_random_pseudo_bytes(13))
)
base64_encode 返回更广泛的字母数字字符 rtrim 有时会在末尾删除 =

例子:

32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4 b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8 y67Q86ffd83G0z00M0Z152f7O2ADcY313gD7a774fc5FF069zdb5b7

这对于为用户创建界面并不是非常可配置的,但出于某些目的是可以的。增加字符数以解决缺少特殊字符的问题。

【讨论】:

【参考方案17】:
    创建一个包含此代码的文件。

    像在 cmets 中那样称呼它。

    <?php 
    
    /**
    * @usage  :
    *       include_once($path . '/Password.php');
    *       $Password = new Password;
    *       $pwd = $Password->createPassword(10);
    *       return $pwd;
    * 
    */
    
    class Password 
    
        public function createPassword($length = 15) 
            $response = [];
            $response['pwd'] = $this->generate($length);
            $response['hashPwd'] = $this->hashPwd( $response['pwd'] );
            return $response;
        
    
        private function generate($length = 15) 
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()/?,><";
            return substr(str_shuffle($chars),0,$length);
        
    
        private function hashPwd($pwd) 
            return hash('sha256', $pwd);
        
    
    
    
    ?>
    

【讨论】:

【参考方案18】:

我创建了一个更全面、更安全的密码脚本。这将创建两个大写字母、两个小写字母、两个数字和两个特殊字符的组合。共 8 个字符。

$char = [range('A','Z'),range('a','z'),range(0,9),['*','%','$','#','@','!','+','?','.']];
$pw = '';
for($a = 0; $a < count($char); $a++)

    $randomkeys = array_rand($char[$a], 2);
    $pw .= $char[$a][$randomkeys[0]].$char[$a][$randomkeys[1]];

$userPassword = str_shuffle($pw);

【讨论】:

【参考方案19】:
//define a function. It is only 3 lines!   
function generateRandomPassword($length = 5)
    $chars = "0123456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
    return substr(str_shuffle($chars),0,$length);


//usage
echo generateRandomPassword(5); //random password legth: 5
echo generateRandomPassword(6); //random password legth: 6
echo generateRandomPassword(7); //random password legth: 7

【讨论】:

这实际上是(非常?)错误的。它实际上只使用字母表中的每个字符一次,因此严重缩小了所有可能值的空间(与破解相关)。【参考方案20】:

我的回答和上面的一些类似,但是我去掉了元音、数字 1 和 0、字母 i、j、I、l、O、o、Q、q、X、x、Y、y、W、 w。原因是:第一个很容易混淆(如 l 和 1,取决于字体),其余的(以 Q 开头)是因为它们在我的语言中不存在,所以它们可能有点奇怪超级终端用户。字符串仍然足够长。另外,我知道使用一些特殊标志会很理想,但它们也无法与某些最终用户相处。

function generatePassword($length = 8) 

$chars = '23456789bcdfhkmnprstvzBCDFHJKLMNPRSTVZ';
$shuffled = str_shuffle($chars);
$result = mb_substr($shuffled, 0, $length);

return $result;

另外,通过这种方式,我们避免重复相同的字母和数字(不包括匹配大小写)

【讨论】:

【参考方案21】:

这是我对选项列表的贡献。

此功能可确保满足密码策略。

  function password_generate($length=8, $min_lowercases=1, $min_uppercases=1, $min_numbers=1, $min_specials=0) 

    $lowercases = 'abcdefghijklmnopqrstuvwxyz';
    $uppercases = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $numbers = '0123456789';
    $specials = '!#%&/()[]+-';

    $absolutes = '';
    if ($min_lowercases && !is_bool($min_lowercases)) $absolutes .= substr(str_shuffle(str_repeat($lowercases, $min_lowercases)), 0, $min_lowercases);
    if ($min_uppercases && !is_bool($min_uppercases)) $absolutes .= substr(str_shuffle(str_repeat($uppercases, $min_uppercases)), 0, $min_uppercases);
    if ($min_numbers && !is_bool($min_numbers)) $absolutes .= substr(str_shuffle(str_repeat($numbers, $min_numbers)), 0, $min_numbers);
    if ($min_specials && !is_bool($min_specials)) $absolutes .= substr(str_shuffle(str_repeat($specials, $min_specials)), 0, $min_specials);

    $remaining = $length - strlen($absolutes);

    $characters = '';
    if ($min_lowercases !== false) $characters .= substr(str_shuffle(str_repeat($lowercases, $remaining)), 0, $remaining);
    if ($min_uppercases !== false) $characters .= substr(str_shuffle(str_repeat($uppercases, $remaining)), 0, $remaining);
    if ($min_numbers !== false) $characters .= substr(str_shuffle(str_repeat($numbers, $remaining)), 0, $remaining);
    if ($min_specials !== false) $characters .= substr(str_shuffle(str_repeat($specials, $remaining)), 0, $remaining);

    $password = str_shuffle($absolutes . substr($characters, 0, $remaining));

    return $password;
  

$min_* 参数可以有以下值:

1-999 = 必需 真 = 可选 false = 禁用

可以这样使用:

echo password_generate(8); // Outputs a random 8 characters long password

10 个字符的密码,每组至少包含 2 个字符:

echo password_generate(10, 2, 2, 2, 2);

仅输出 6 个随机数

echo password_generate(6, false, false, true, false);

【讨论】:

【参考方案22】:

生成长度为 8 的强密码,其中至少包含一个小写字母、一个大写字母、一个数字和一个特殊字符。您也可以更改代码中的长度。

function checkForCharacterCondition($string) 
    return (bool) preg_match('/(?=.*([A-Z]))(?=.*([a-z]))(?=.*([0-9]))(?=.*([~`\!@#\$%\^&\*\(\)_\\\[\]]))/', $string);


$j = 1;

function generate_pass() 
    global $j;
    $allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_[]';
    $pass = '';
    $length = 8;
    $max = mb_strlen($allowedCharacters, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) 
        $pass .= $allowedCharacters[random_int(0, $max)];
    

    if (checkForCharacterCondition($pass))
        return '<br><strong>Selected password: </strong>'.$pass;
    else
        echo 'Iteration '.$j.':  <strong>'.$pass.'</strong>  Rejected<br>';
        $j++;
        return generate_pass();
    



echo generate_pass();

【讨论】:

【参考方案23】:

此函数将根据参数中的规则生成密码

function random_password( $length = 8, $characters = true, $numbers = true, $case_sensitive = true, $hash = true ) 

    $password = '';

    if($characters)
    
        $charLength = $length;
        if($numbers) $charLength-=2;
        if($case_sensitive) $charLength-=2;
        if($hash) $charLength-=2;
        $chars = "abcdefghijklmnopqrstuvwxyz";
        $password.= substr( str_shuffle( $chars ), 0, $charLength );
    

    if($numbers)
    
        $numbersLength = $length;
        if($characters) $numbersLength-=2;
        if($case_sensitive) $numbersLength-=2;
        if($hash) $numbersLength-=2;
        $chars = "0123456789";
        $password.= substr( str_shuffle( $chars ), 0, $numbersLength );
    

    if($case_sensitive)
    
        $UpperCaseLength = $length;
        if($characters) $UpperCaseLength-=2;
        if($numbers) $UpperCaseLength-=2;
        if($hash) $UpperCaseLength-=2;
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $password.= substr( str_shuffle( $chars ), 0, $UpperCaseLength );
    

    if($hash)
    
        $hashLength = $length;
        if($characters) $hashLength-=2;
        if($numbers) $hashLength-=2;
        if($case_sensitive) $hashLength-=2;
        $chars = "!@#$%^&*()_-=+;:,.?";
        $password.= substr( str_shuffle( $chars ), 0, $hashLength );
    

    $password = str_shuffle( $password );
    return $password;

【讨论】:

【参考方案24】:

这是我对随机纯密码生成助手的看法。

确保密码包含数字、大小写字母以及最少 3 个特殊字符。

密码长度在 11 到 30 之间。

function plainPassword(): string

    $numbers = array_rand(range(0, 9), rand(3, 9));
    $uppercase = array_rand(array_flip(range('A', 'Z')), rand(2, 8));
    $lowercase = array_rand(array_flip(range('a', 'z')), rand(3, 8));
    $special = array_rand(array_flip(['@', '#', '$', '!', '%', '*', '?', '&']), rand(3, 5));

    $password = array_merge(
        $numbers,
        $uppercase,
        $lowercase,
        $special
    );

    shuffle($password);

    return implode($password);

【讨论】:

【参考方案25】:

生成随机密码字符串

function generate_randompassword($passlength = 8)
    $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#%^*>\$@?/[]=+';
    $pass = array(); //remember to declare $pass as an array
    $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
    for ($i = 0; $i < $passlength; $i++) 
        $n = rand(0, $alphaLength);
        $pass[] = $alphabet[$n];
    
    return implode($pass); //turn the array into a string

【讨论】:

【参考方案26】:
function password_generate($n, $l, $s) 

  $numbers = '1234567890';
  $letters = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcefghijklmnopqrstuvwxyz';
  $special = '--!=!@@#++%';
  return substr(str_shuffle($numbers), 0, $n).substr(str_shuffle($letters), 0, $l).substr(str_shuffle($special), 0, $s);


echo password_generate(2,9,1);

【讨论】:

出于密码生成目的,只能使用安全随机生成器,例如random_bytesrandom_int。许多其他随机值生成解决方案,包括涉及time()microtime()uniqid()rand()mt_rand()str_shuffle()array_rand()shuffle() 的解决方案,都更加可预测,并且如果随机字符串将用作密码或其他秘密值,则不适合。见:***.com/questions/4570980/…

以上是关于在php中生成随机密码的主要内容,如果未能解决你的问题,请参考以下文章

Php中常见的4种随机密码生成方法详解

如何在 Laravel 中生成和验证随机(和临时)密码?

如何在 Zend Framework 中生成用于重置密码的随机密码或临时 URL?

PHP 中的安全随机数生成

在 Python 中生成随机数的标准方法是啥?

在 Python 中生成随机数的标准方法是啥?