我试图在PHP中创建一个随机字符串,我得到绝对没有输出:
<?php
function RandomString()
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randstring = '';
for ($i = 0; $i < 10; $i++) {
$randstring = $characters[rand(0, strlen($characters))];
}
return $randstring;
}
RandomString();
echo $randstring;
我做错了什么?
只使用PHP本地函数的参数化一行程序,从PHP 5.1.0开始工作
str_shuffle(implode('', (array_intersect_key(($map = array_map('chr', array_merge(array_map('mt_rand', array_fill(0, $length = 25, 48), array_fill(0,$length,57)),array_map('mt_rand', array_fill(0, $length, 65), array_fill(0,$length,90)),array_map('mt_rand', array_fill(0, $length, 97), array_fill(0,$length,122))))), array_flip($keys = array_rand($map, $length))))))
一个完整的解决方案(课程加测试),部分基于上面的一些建议…
class TokenFactory
{
private const LENGTH = 12;
private const ALLOWED = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ~!@#$%^&*{}';
private const MIN_NUMBER_OF_DIGITS = 1;
private const MIN_NUMBER_OF_CAPS = 1;
private const MIN_NUMBER_OF_SPECIALS = 1;
private const MIN_NUMBER_OF_LETTERS = 1;
/**
* @return string
* @throws \Exception
*/
public function make(): string
{
$pass = $this->generateToken();
if ($this->isTokenValid($pass)) {
return $pass;
} else {
return $this->make();
}
}
/**
* @return string
* @throws \Exception
*/
private function generateToken(): string
{
$allowedCharacters = self::ALLOWED;
$token = '';
$max = mb_strlen($allowedCharacters, '8bit') - 1;
for ($i = 0; $i < self::LENGTH; ++$i) {
$token .= $allowedCharacters[random_int(0, $max)];
}
return $token;
}
/**
* @param $token
* @return bool
*/
private function isTokenValid($token): bool
{
$numberOfDigits = preg_match_all("/[0-9]/", $token);
$numberOfCaps = preg_match_all("/[A-Z]/", $token);
$numberOfSpecials = preg_match_all("/[~!@#\$%^&*{}]/", $token);
$numberOfLetters = preg_match_all("/[a-z]/", $token);
return
$numberOfDigits > self::MIN_NUMBER_OF_DIGITS
&& $numberOfCaps > self::MIN_NUMBER_OF_CAPS
&& $numberOfSpecials > self::MIN_NUMBER_OF_SPECIALS
&& $numberOfLetters > self::MIN_NUMBER_OF_LETTERS
;
}
}
class TokenFactoryTest
{
public function test_correct_syntax()
{
/**
* Arrange
*/
$length = 12;
$numberOfChecks = 1000;
/**
* Act & Assert
*/
$class = new TokenFactory();
$i = 0;
while ($i < $numberOfChecks) {
$generatedToken = $class->make();
$numberOfDigits = preg_match_all( "/[0-9]/", $generatedToken );
$numberOfCaps = preg_match_all( "/[A-Z]/", $generatedToken );
$numberOfSpecials = preg_match_all("/[~!@#\$%^&*{}]/", $generatedToken);
$numberOfLetters = preg_match_all("/[a-z]/", $generatedToken);
Assert::assertEquals($length, strlen($generatedToken));
Assert::assertTrue($numberOfDigits >= 1, 'Digit error: ' . $generatedToken);
Assert::assertTrue($numberOfCaps >= 1, 'Caps error: ' . $generatedToken);
Assert::assertTrue($numberOfSpecials >= 1, 'Specials error: ' . $generatedToken);
Assert::assertTrue($numberOfLetters >= 1, 'Letters error: ' . $generatedToken);
$i++;
}
}
}
顺便说一句,请确保在适合您需要的地方捕获该异常!
这是一个简单的句子。您将得到至少一个小写字母、一个大写字母、一个数字和一个符号。使用random_int,这应该是密码安全的。不过,我并不认为这是安全的。我不是安全专家。
复制+粘贴:(只需将$len更改为所需的长度。)
$len=26;for ($chars = array('0123456789','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ','!@#$%^&*()_+-='),$randomString="",$i=0;$i<$len;$i++)$randomString .= substr($chars[$i%4], random_int(0,strlen($chars[$i%4])), 1);
echo $randomString;
再细分一下:
for (
$chars = array('0123456789','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ','!@#$%^&*()_+-='),
$randomString="",
$i=0;
$i<12;$i++)
$randomString .=
substr($chars[$i%4],
random_int(0, strlen($chars[$i%4])), 1);
我在循环中使用$chars[$ I %4]来选择从哪组字符中获取随机字符。它保证数组中的每一组字符都有多个字符。
它肯定可以改进(随机设置每个字符集的数量),但对于我的目的来说已经足够好了。