我试图在PHP中创建一个随机字符串,我得到绝对没有输出:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;

我做错了什么?


当前回答

具有上面讨论的一些函数的类。

$options['numeric'] = true;
$options['uppercase'] = true;
$options['lowercase'] = true;
$new = new RandomString($options);

class RandomString
{
    /**
     * @var array
     */
    private $default = ['numeric' => true, 'uppercase' => true, 'lowercase' => true];

    /**
     * @var array
     */
    private $options;

    /**
     * array
     */
    private $whitelist = ['numeric', 'uppercase', 'lowercase'];

    /**
     * RandomString constructor.
     *
     * @param array $options
     */
    public function __construct(array $options = [])
    {
        $this->options = $this->default;
        if(!empty($options))
        {
            $options = array_intersect_key($options, array_flip($this->whitelist));
            if(empty($options))
            {
                $this->options = $this->default;
            }else
            {
                $this->options = $options;
            }
        }
    }

    /**
     * @return string
     */
    private function returnCharacters(){

        $options = $this->options;

        $numbers = '0123456789';
        $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $lowercase = "abcdefghijklmnopqrstuvwxyz";

        $characters = '';
        if(isset($options['numeric']) && $options['numeric'] === true){
            $characters .= $numbers;
        }

        if(isset($options['uppercase']) && $options['uppercase'] === true){
            $characters .= $uppercase;
        }

        if(isset($options['lowercase']) && $options['lowercase'] === true){
            $characters .= $lowercase;
        }
        return $characters;
    }

    /**
     * @param $length
     * @param $quantity
     * @return string
     */
    public function randomString($length, $quantity) {

        $string = '';
        $characters = $this->returnCharacters();

        for ($j = 0; $j < $quantity; $j++) {
            for($i = 0; $i < $length; $i++){
                $string .= $characters[mt_rand(0, strlen($characters) - 1)];
            }
            $string .= "\n";
        }
        return $string;
    }

    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * @return mixed
     */
    public function getWhitelist()
    {
        return $this->whitelist;
    }

其他回答

注意:str_shuffle()内部使用rand(),不适合用于加密目的(例如生成随机密码)。你需要一个安全的随机数生成器。它也不允许字符重复。

还有一种方法。

UPDATED(现在这会生成任意长度的字符串):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)

就是这样。:)

这个问题有很多答案,但没有一个是利用加密安全伪随机数生成器(CSPRNG)的。

简单、安全、正确的答案是使用RandomLib,不要白费力气。

对于那些坚持发明自己的解决方案的人,PHP 7.0.0将为此目的提供random_int();如果你还在使用PHP 5。x,我们为random_int()写了一个PHP 5的polyfill,这样你甚至可以在升级到PHP 7之前使用新的API。

在PHP中安全地生成随机整数并不是一项简单的任务。在生产环境中部署自己开发的算法之前,您应该始终与常驻StackExchange密码学专家进行检查。

有了安全的整数生成器,使用CSPRNG生成随机字符串就像在公园里散步一样简单。

创建安全的随机字符串

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * 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(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}

用法:

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();

演示:https://3v4l.org/IMJGF(忽略PHP 5失败;它需要random_compat)

function randomName($length = 8) {
  $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
  $max = count($values) - 1;
  $str = chr(mt_rand(97, 122));
  for ($i = 1; $i < $length; $i++) {
    $str .= chr($values[mt_rand(0, $max)]);
  }
  return $str;
}

一个非常快速的方法是这样做:

substr(md5(rand()),0,10);

这将生成一个长度为10个字符的随机字符串。当然,有些人可能会说这在计算方面有点重,但现在的处理器已经优化到可以快速运行md5或sha256算法。当然,如果rand()函数返回相同的值,结果将是相同的,有1 / 32767的机会是相同的。如果安全性是问题,那么只需将rand()更改为mt_rand()

首先,定义你想要使用的字母:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;

然后,使用openssl_random_pseudo_bytes()生成适当的随机数据:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);

最后,使用这些随机数据创建密码。因为$random中的每个字符可以是chr(0)直到chr(255),代码使用其序数与$alphabet_length除法后的余数来确保只从字母表中选择字符(注意这样做会偏向随机性):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}

或者,通常更好的方法是使用RandomLib和SecurityLib:

use SecurityLib\Strength;

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

$password = $generator->generateString(12, $alphabet);