我试图在php中生成一个随机密码。

但是我得到的都是'a'返回类型是数组类型,我希望它是字符串。对如何修改代码有什么想法吗?

谢谢。

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

当前回答

安全警告:rand()不是一个加密安全的伪随机数生成器。在其他地方寻找在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

其他回答

你最好的选择是ircmaxell的RandomLib库。

使用的例子:

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

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

它产生的字符串比普通的随机函数(如shuffle()和rand()(这是你通常想要的敏感信息,如密码,盐和密钥)更强的随机性。

我知道您正在尝试以特定的方式生成密码,但您可能也想看看这个方法……

$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!

这是我的密码助手

class PasswordHelper
{
    /**
    * generate a secured random password
    */
    public static function generatePassword(
        int $lowerCaseCount=8, 
        int $upperCaseCount=8, 
        int $numberCount=8, 
        int $specialCount=4
    ): string
    {
        $lowerCase  = 'abcdefghijklmnopqrstuvwxyz';
        $upperCase  = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $number     = '0123456789';
        $special    = '!@#$%^&*';

        $password = self::getRandom($lowerCase, $lowerCaseCount);
        $password .= self::getRandom($upperCase, $upperCaseCount);
        $password .= self::getRandom($number, $numberCount);
        $password .= self::getRandom($special, $specialCount);

        return str_shuffle($password);
    }

    /**
     * get a random string from a set of characters
     */
    public static function getRandom($set, $length): string
    {
        $rand = '';
        $setLength = strlen($set);

        for ($i = 0; $i < $length; $i++)
        {
            $rand .= $set[random_int(0, $setLength - 1)];
        }

        return $rand;
    }
}

用法:

PasswordHelper::generatePassword()或PasswordHelper::generatePassword(2,4,5,3)

另一个(仅限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)), "=");
}

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

一个比你想要的更小的字符空间,这样在相同的熵下,强制操作更容易,或者密码必须更长 不被认为是加密安全的RNG 一些第三方库的需求,我认为这可能是有趣的,展示什么可能需要自己做

这个答案将规避计数/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))));

The 3/4 factor is due to the fact that base64 encoding results in a string that has a length at least a third bigger than the byte string. The result will be exact for $n being a multiple of 4 and up to 3 characters longer otherwise. Since the extra characters are predominantly the padding character =, if we for some reason had a constraint that the password be an exact length, then we can truncate it to the length we want. This is especially because for a given $n, all passwords would end with the same number of these, so that an attacker who had access to a result password, would have up to 2 less characters to guess.


对于额外的学分,如果我们想要满足OP的问题中的确切规格,那么我们将不得不做更多的工作。在这里我将放弃碱基转换方法,而使用一个快速而肮脏的方法。这两种方法都需要产生比结果中所使用的更多的随机性,因为字母表有62个条目。

对于结果中的额外字符,我们可以简单地将它们从结果字符串中丢弃。如果我们在字节串中开始有8个字节,那么多达25%的base64字符将是这些“不受欢迎的”字符,因此简单地丢弃这些字符将导致不少于OP所需的字符串。然后我们可以简单地截断它以得到准确的长度:

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

如果您生成较长的密码,填充字符=在中间结果中所占的比例会越来越小,这样您就可以实现更精简的方法(如果需要耗尽用于PRNG的熵池)。