Как создать случайную строку с помощью PHP? - PullRequest
56 голосов
/ 12 мая 2009

Я знаю, что функция rand в PHP генерирует случайные целые числа, но как лучше всего создать случайную строку, такую ​​как:

Оригинальная строка, 9 символов

$string = 'abcdefghi';

Пример случайного ограничения строки до 6 символов

$string = 'ibfeca';

ОБНОВЛЕНИЕ: Я нашел тонны этих типов функций, в основном я пытаюсь понять логику каждого шага.

ОБНОВЛЕНИЕ: функция должна генерировать любое количество символов по мере необходимости.

Пожалуйста, прокомментируйте детали, если ответите.

Ответы [ 19 ]

98 голосов
/ 12 мая 2009

Если вы хотите разрешить повторяющиеся вхождения символов, вы можете использовать эту функцию:

function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
    $str = '';
    $count = strlen($charset);
    while ($length--) {
        $str .= $charset[mt_rand(0, $count-1)];
    }
    return $str;
}

Основной алгоритм состоит в том, чтобы <<em> длина > умножить случайное число от 0 до <<em> количество символов > - 1, которое мы используем в качестве индекса для выбора символа из нашего набора объединить эти символы. Границы 0 и <<em> количество символов > - 1 представляют границы строки $charset, поскольку первый символ адресуется $charset[0], а последний - $charset[count($charset) - 1].

91 голосов
/ 12 мая 2009

Ну, вы не уточнили все вопросы, которые я задал в своем комментарии, но я предполагаю, что вам нужна функция, которая может принимать строку «возможных» символов и длину строки для возврата. Прокомментировано в соответствии с просьбой, с использованием большего количества переменных, чем обычно, для ясности:

function get_random_string($valid_chars, $length)
{
    // start with an empty random string
    $random_string = "";

    // count the number of chars in the valid chars string so we know how many choices we have
    $num_valid_chars = strlen($valid_chars);

    // repeat the steps until we've created a string of the right length
    for ($i = 0; $i < $length; $i++)
    {
        // pick a random number from 1 up to the number of valid chars
        $random_pick = mt_rand(1, $num_valid_chars);

        // take the random character out of the string of valid chars
        // subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
        $random_char = $valid_chars[$random_pick-1];

        // add the randomly-chosen char onto the end of our string so far
        $random_string .= $random_char;
    }

    // return our finished random string
    return $random_string;
}

Чтобы вызвать эту функцию с данными вашего примера, вы бы назвали ее примерно так:

$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);

Обратите внимание, что эта функция не проверяет уникальность переданных ей допустимых символов. Например, если вы называете его с допустимой строкой символов 'AAAB', вероятность выбора буквы A для каждой буквы будет в три раза выше. Это может рассматриваться как ошибка или функция, в зависимости от ваших потребностей.

52 голосов
/ 21 июня 2012

Мой любимый:

 echo substr(md5(rand()), 0, 7);
24 голосов
/ 22 апреля 2015

Итак, позвольте мне начать со слов ИСПОЛЬЗОВАТЬ БИБЛИОТЕКУ . Многие существуют:

Суть проблемы - почти каждый ответ на этой странице подвержен атаке. mt_rand(), rand(), lcg_value() и uniqid() все уязвимы для атаки .

Хорошая система будет использовать /dev/urandom из файловой системы или mcrypt_create_iv()MCRYPT_DEV_URANDOM) или openssl_pseudo_random_bytes(). Что все вышеперечисленное делает. PHP 7 будет поставляться с двумя новыми функциями random_bytes($len) и random_int($min, $max), которые также безопасны.

Имейте в виду, что большинство из этих функций (кроме random_int()) возвращают «необработанные строки», то есть они могут содержать любой символ ASCII из 0 - 255. Если вам нужна строка для печати, я бы рекомендовал пропустить результат через base64_encode().

17 голосов
/ 12 мая 2009
function generate_random_string($name_length = 8) {
    $alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}

Обновлен код в соответствии с отличным предложением mzhang в комментариях ниже.

9 голосов
/ 11 августа 2013

Лучшая и обновленная версия отличного ответа @ taskamiski:

Лучшая версия, используя mt_rand() вместо rand():

echo md5(mt_rand()); // 32 char string = 128bit

Еще лучше, для более длинных строк, используя функцию hash(), которая позволяет выбирать алгоритмы хеширования:

echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string

Если вы хотите сократить результат до, скажем, 50 символов, сделайте это так:

echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string
6 голосов
/ 12 мая 2009

Объединение символов в конце должно быть более эффективным, чем повторное объединение строк.

Редактировать # 1: Добавлена ​​опция, позволяющая избежать повторения символов.

Редактирование # 2: создает исключение, чтобы избежать попадания в бесконечный цикл, если выбран $ norepeat и $ len больше, чем набор символов для выбора.

Редактирование # 3: использует ключи массива для хранения выбранных случайных символов, когда выбран $ norepeat, поскольку поиск по ключу ассоциативного массива быстрее, чем линейный поиск в массиве.

function rand_str($len, $norepeat = true)
{
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $max = strlen($chars) - 1;

    if ($norepeat && len > $max + 1) {
        throw new Exception("Non repetitive random string can't be longer than charset");
    }

    $rand_chars = array();

    while ($len) {
        $picked = $chars[mt_rand(0, $max)];

        if ($norepeat) {
            if (!array_key_exists($picked, $rand_chars)) {
                $rand_chars[$picked] = true;
                $len--;
            }
        }
        else {
            $rand_chars[] = $picked;
            $len--;
        }
    }

    return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);   
}
4 голосов
/ 19 октября 2012

это сгенерирует случайную строку

function generateRandomString($length=10) {
    $original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
    $original_string = implode("", $original_string);
    return substr(str_shuffle($original_string), 0, $length);
}
echo generateRandomString(6);
2 голосов
/ 20 августа 2014

Думаю, я тоже добавлю сюда свой вклад.

function random_string($length) {
    $bytes_1 = openssl_random_pseudo_bytes($length);
    $hex_1 = bin2hex($bytes_1);
    $random_numbers = substr(sha1(rand()), 0, $length);
    $bytes_2 = openssl_random_pseudo_bytes($length);
    $hex_2 = bin2hex($bytes_2);
    $combined_chars = $hex_1 . $random_numbers . $hex_2;
    $chars_crypted = hash('sha512', $combined_chars);

    return $chars_crypted;
}

Спасибо

2 голосов
/ 30 сентября 2015

Зачем вам нужна случайная строка?

Будет ли это использоваться для чего-либо удаленно аналогичного паролю?

Если ваша случайная строка вообще требует каких-либо свойств безопасности, вы должны использовать random_int() функцию PHP 7 вместо всех небезопасных mt_rand() ответов в этой теме.

/**
 * Generate a random string
 * 
 * @link https://paragonie.com/b/JvICXzh_jhLyt4y3
 *
 * @param int $length - How long should our random string be?
 * @param string $charset - A string of all possible characters to choose from
 * @return string
 */
function random_str($length = 32, $charset = 'abcdefghijklmnopqrstuvwxyz')
{
    // Type checks:
    if (!is_numeric($length)) {
        throw new InvalidArgumentException(
            'random_str - Argument 1 - expected an integer'
        );
    }
    if (!is_string($charset)) {
        throw new InvalidArgumentException(
            'random_str - Argument 2 - expected a string'
        );
    }

    if ($length < 1) {
        // Just return an empty string. Any value < 1 is meaningless.
        return '';
    }
    // This is the maximum index for all of the characters in the string $charset
    $charset_max = strlen($charset) - 1;
    if ($charset_max < 1) {
        // Avoid letting users do: random_str($int, 'a'); -> 'aaaaa...'
        throw new LogicException(
            'random_str - Argument 2 - expected a string at least 2 characters long'
        );
    }
    // Now that we have good data, this is the meat of our function:
    $random_str = '';
    for ($i = 0; $i < $length; ++$i) {
        $r = random_int(0, $charset_max);
        $random_str .= $charset[$r];
    }
    return $random_str;
}

Если вы еще не используете PHP 7 (что, вероятно, так и есть, поскольку на момент написания этой статьи еще не было выпущено), вам понадобится paragonie / random_compat , который Пользовательская реализация random_bytes() и random_int() для проектов PHP 5.

В контексте безопасности всегда используйте random_int(), а не rand(), mt_rand() и т. Д. См. Также ответ ircmaxell .

...