Подтвердить что ты не робот

Как создать случайную строку с помощью PHP?

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

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

$string = 'abcdefghi';

Пример случайной строки, ограничивающей 6 символов

$string = 'ibfeca';

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

UPDATE: функция должна генерировать любое количество символов по мере необходимости.

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

4b9b3361

Ответ 1

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

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 для каждой буквы в виде B. Это можно считать ошибкой или функцией в зависимости от ваших потребностей.

Ответ 2

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

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

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

Ответ 3

Мой любимый:

 echo substr(md5(rand()), 0, 7);

Ответ 4

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

Ядро проблемы почти каждый ответ на этой странице восприимчив к атаке. 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().

Ответ 5

function generate_random_string($name_length = 8) {
    $alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}

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

Ответ 6

Лучшая и обновленная версия отличного ответа @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

Ответ 7

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

Изменить # 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);   
}

Ответ 8

это приведет к генерации случайной строки

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

Ответ 9

Большинство аспектов этого вопроса уже обсуждались, но я бы рекомендовал небольшое обновление: Если вы используете это для розничного использования, я бы избегал домена ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789

и вместо этого используйте: ABCDEFGHJKMNPQRSTUVWXY3456789

Конечно, вы получаете гораздо меньше символов, но это экономит много хлопот, так как клиенты не могут ошибаться 0 для O или 1 для l или 2 для Z. Также вы можете делать UPPER на входе и клиенты могут затем вводить буквы верхнего или нижнего регистра, что также иногда сбивает с толку, так как они могут выглядеть одинаково.

Ответ 10

Думаю, я добавлю свой вклад и здесь.

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

Спасибо

Ответ 11

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

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

Если ваша случайная строка требует каких-либо свойств безопасности вообще, вы должны использовать функцию PHP 7 random_int() вместо всех небезопасных ответов 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, который представляет собой реализацию userland random_bytes() и random_int() для проектов PHP 5.

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

Ответ 12

// @author http://codeascraft.etsy.com/2012/07/19/better-random-numbers-in-php-using-devurandom/                                                
function devurandom_rand($min = 0, $max = 0x7FFFFFFF)
{
    $diff = $max - $min;
    if ($diff < 0 || $diff > 0x7FFFFFFF) {
        throw new RuntimeException('Bad range');
    }
    $bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
    if ($bytes === false || strlen($bytes) != 4) {
        throw new RuntimeException('Unable to get 4 bytes');
    }
    $ary = unpack('Nint', $bytes);
    $val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe                           
    $fp = (float) $val / 2147483647.0; // convert to [0,1]                          
    return round($fp * $diff) + $min;
}

function build_token($length = 60, $characters_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
    $map_length = mb_strlen($characters_map)-1;
    $token = '';
    while ($length--) {
        $token .= mb_substr($characters_map, devurandom_rand(0,$map_length),1);
    }
    return $token;
}

Это будет работать только в среде UNIX, где PHP скомпилирован с mcrypt.

Ответ 13

Вы хотите создать свой пароль путем случайной перестановки исходных букв? Должны ли они просто содержать уникальные символы?

Используйте rand для выбора случайных букв по индексу.

Ответ 14

Это старый вопрос, но я хочу попробовать опубликовать свое решение... Я всегда использую эту функцию для генерации произвольной случайной буквенно-цифровой строки...

<?php
  function random_alphanumeric($length) {
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
    $my_string = '';
    for ($i = 0; $i < $length; $i++) {
      $pos = mt_rand(0, strlen($chars) -1);
      $my_string .= substr($chars, $pos, 1);
    }
    return $my_string;
  }
  $test = random_alphanumeric(50); // 50 characters
  echo $test;
?>

test: UFOruSSTCPIqxTRIIMTRkqjOGidcVlhYaS9gtwttxglheVugFM

если вам нужны две или более уникальные строки, вы можете использовать этот трюк...

$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
  $string_1 = random_alphanumeric(50);
  $string_2 = random_alphanumeric(50);
  if ($string_1 != $string_2) {
     break;
  }
}
echo $string_1;
echo "<br>\n";
echo $string_2;

$ string_1: tMYicqLCHEvENwYbMUUVGTfkROxKIekEB2YXx5FHyVByp3mlJO

$ string_2: XdMNJYpMlFRKFDlF6GhVn6jsBVNQ1BCCevj8yK2niFOgpDI2MU

Я надеюсь, что это поможет.

Ответ 15

echo substr(bin2hex(random_bytes(14)), 0, $length);

этот код получает случайные байты, которые преобразуются из двоичного в шестнадцатеричное, а затем принимает подстроку этой шестнадцатеричной строки, пока вы вводите переменную $ length

Ответ 16

вы можете создать массив символов, а затем использовать rand(), чтобы выбрать письмо из массива и добавить его в строку.

$letters = array( [0] => 'a' [1] => 'b' [2] => 'c' [3] => 'd' ... [25] = 'z');

$lengthOfString = 10;
$str = '';

while( $lengthOfString-- )
{
   $str .= $letters[rand(0,25)];
}
echo $str;

* обратите внимание, что это позволяет повторять символы

Ответ 17

Это построено на Gumbo solution, добавив функциональность, чтобы перечислить набор символов, которые нужно пропустить в базовом наборе символов. Случайная строка выбирает символы из $base_charset, которые также не отображаются в $skip_charset.

/* Make a random string of length using characters from $charset, excluding $skip_chars.
 * @param length (integer) length of return value
 * @param skip_chars (string) characters to be excluded from $charset
 * @param charset (string) characters of posibilities for characters in return val
 * @return (string) random string of length $length    */
function rand_string(
        $length, 
        $skip_charset = '', 
        $base_charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'){
  $skip_len = strlen($skip_charset);
  for ($i = 0; $i<$skip_len; $i++){
    $base_charset = str_replace($skip_charset[$i], '', $base_charset);
  }
  cvar_dump($base_charset, '$base_charset after replace');
  $str = '';
  $count = strlen($base_charset);
  while ($length--) {
    $str .= $base_charset[mt_rand(0, $count - 1)];
  }
  return $str;
}

Вот несколько примеров использования. В первых двух примерах используется значение по умолчанию для $base_charset. Последний пример явно определяет $base_charset.

echo rand_string(15, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
//  470620078953298
echo rand_string(8, 'abcdefghijklmnopqrstuvwxyz0123456789');
//  UKLIHOTFSUZMFPU
echo rand_string(15, 'def', 'abcdef');
//  cbcbbccbabccaba

Ответ 18

Ну, я искал решение, и я использовал @Bhch Birch решение, объединенное с @Gumbo. Вот что я придумал:

function get_random_string($length, $valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456790!·$%&/()=?¿¡',.-;:+*`+´ç")
{
    $random_string = "";
    $num_valid_chars = strlen($valid_chars);
    for ($i = 0; $i < $length; $i++, $random_string .= $valid_chars[mt_rand(1, $num_valid_chars)-1]);
    return $random_string;
}

Я думаю, что комментарии в значительной степени неудобны, так как ответы, которые я использовал для создания этого, уже тщательно прокомментированы. Ура!

Ответ 19

Если вас не беспокоит время, память или КПД, и если ваша система может справиться с этим, почему бы не попробовать этот алгоритм?!

function randStr($len, $charset = 'abcdABCD0123') {
    $out = '';
    $str = array();

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $str[$i] = $charset;

        shuffle($str);
        $charset .= implode($charset, $str);
        $charset = str_shuffle($charset);
    }

    $str = array_flip($str);
    $str = array_keys($str);

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        shuffle($str);
    }

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

    for ($i = 0; $i < strlen($str); $i++) {
        $index = mt_rand(1, strlen($str));
        $out .= $str[$index - 1];
    }

    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $out = str_shuffle($out);
    }

    return substr($out, 0, $len);
}

Может быть, это будет лучше читать, если он использует рекурсию, но я не уверен, что PHP использует хвостовую рекурсию или нет...