以前的答案会生成不安全或难以输入的密码。
这是安全的,并且提供了用户更有可能实际使用的密码,而不是因为一些薄弱的东西而被丢弃。
// NOTE: On PHP 5.x you will need to install https://github.com/paragonie/random_compat
/**
* Generate a password that can easily be typed by users.
*
* By default, this will sacrifice strength by skipping characters that can cause
* confusion. Set $allowAmbiguous to allow these characters.
*/
static public function generatePassword($length=12, $mixedCase=true, $numericCount=2, $symbolCount=1, $allowAmbiguous=false, $allowRepeatingCharacters=false)
{
// sanity check to prevent endless loop
if ($numericCount + $symbolCount > $length) {
throw new \Exception('generatePassword(): $numericCount + $symbolCount are too high');
}
// generate a basic password with just alphabetic characters
$chars = 'qwertyupasdfghjkzxcvbnm';
if ($mixedCase) {
$chars .= 'QWERTYUPASDFGHJKZXCVBNML';
}
if ($allowAmbiguous) {
$chars .= 'iol';
if ($mixedCase) {
$chars .= 'IO';
}
}
$password = '';
foreach (range(1, $length) as $index) {
$char = $chars[random_int(0, strlen($chars) - 1)];
if (!$allowRepeatingCharacters) {
while ($char == substr($password, -1)) {
$char = $chars[random_int(0, strlen($chars) - 1)];
}
}
$password .= $char;
}
// add numeric characters
$takenSubstitutionIndexes = [];
if ($numericCount > 0) {
$chars = '23456789';
if ($allowAmbiguous) {
$chars .= '10';
}
foreach (range(1, $numericCount) as $_) {
$index = random_int(0, strlen($password) - 1);
while (in_array($index, $takenSubstitutionIndexes)) {
$index = random_int(0, strlen($password) - 1);
}
$char = $chars[random_int(0, strlen($chars) - 1)];
if (!$allowRepeatingCharacters) {
while (substr($password, $index - 1, 1) == $char || substr($password, $index + 1, 1) == $char) {
$char = $chars[random_int(0, strlen($chars) - 1)];
}
}
$password[$index] = $char;
$takenSubstitutionIndexes[] = $index;
}
}
// add symbols
$chars = '!@#$%&*=+?';
if ($allowAmbiguous) {
$chars .= '^~-_()[{]};:|\\/,.\'"`<>';
}
if ($symbolCount > 0) {
foreach (range(1, $symbolCount) as $_) {
$index = random_int(0, strlen($password) - 1);
while (in_array($index, $takenSubstitutionIndexes)) {
$index = random_int(0, strlen($password) - 1);
}
$char = $chars[random_int(0, strlen($chars) - 1)];
if (!$allowRepeatingCharacters) {
while (substr($password, $index - 1, 1) == $char || substr($password, $index + 1, 1) == $char) {
$char = $chars[random_int(0, strlen($chars) - 1)];
}
}
$password[$index] = $char;
$takenSubstitutionIndexes[] = $index;
}
}
return $password;
}