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

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

谢谢。

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

当前回答

下面是另一个密码生成器代码片段。 控制长度,数字和特殊字符计数和列表。

其他解决方案的一个问题是,它们没有包含重复字符的选项。而下面的脚本也可以做到这一点。

$length = random_int(30, 40);

$pass = [];

$lowers = range('a', 'z');
$uppers = range('A', 'Z');
$digits = range('0', '9');
$specials = ['.', '-', '_', '^', '#', '(', ')'];

$specialCount = random_int(1, 5);
$digitCount = random_int(1, 9);

for ($i = 0; $i < $length - $specialCount - $digitCount; $i++) { 
    $pass[] = random_int(1, PHP_INT_MAX) % 2 == 0 ? $uppers[array_rand($uppers)] : $lowers[array_rand($lowers)];
}
for ($i = 0; $i < $specialCount; $i++) { 
    $pass[] = $specials[array_rand($specials)];
}
for ($i = 0; $i < $digitCount; $i++) { 
    $pass[] = $digits[array_rand($digits)];
}

shuffle($pass)

$pass = implode('', $pass);

其他回答

//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

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

我。e0m6ngefmj4

EDIT

正如我在评论中提到的,长度意味着暴力攻击比定时攻击更有效,所以不必担心“随机生成器有多安全”。安全性,特别是对于这个用例,需要补充可用性,所以上面的解决方案对于所需的问题已经足够好了。

然而,以防你在搜索安全的随机字符串生成器时偶然发现了这个答案(我假设有些人已经基于响应),对于生成令牌之类的东西,以下是此类代码的生成器的样子:

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);
    }
}

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

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

如果你在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;
}

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

一个比你想要的更小的字符空间,这样在相同的熵下,强制操作更容易,或者密码必须更长 不被认为是加密安全的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的熵池)。