Intereting Posts
Самый быстрый способ удаления значения в списке, разделенном запятыми Не могу найти базовый путь для связки Каков наилучший способ дезинфекции пользовательских ресурсов? Как загрузить файл в codeigniter? Я продолжаю получать сообщение об ошибке на нашем сайте. Предупреждение: mysqli_real_escape_string () ожидает ровно 2 параметра, 1 задано в … PHP – исключить все нерабочие часы / дни из разницы во времени Шаблон модуля Javascript с обратным вызовом Ajax Операция MySQL занимает более минуты, чтобы выполнить mysql: используйте SET или много столбцов? php regex: получить значение src снятие пробелов и ограничение в nl2br () wkhtmltopdf: Какие размеры бумаги действительны? Могу ли я передать ассоциативный массив в качестве аргумента в ReflectionMethod :: invokeArgs? Как прочитать эффективный URL ответа в Guzzle ~ 6.0 JQuery не загружается в голову, а загружается на нижней части тега тела

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

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

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

$string = 'abcdefghi'; 

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

 $string = 'ibfeca'; 

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

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

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

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

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

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

 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] .

Мой любимый:

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

Итак, позвольте мне начать с использования USE A LIBRARY . Многие существуют:

  • RandomCompat
  • RandomLib
  • SecurityMultiTool

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

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

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

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

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

Редактировать # 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); } 

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

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

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

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

благодаря

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

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

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

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

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

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

 // @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 .

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

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

вы можете создать массив символов, а затем использовать 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; 

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

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

ну, я искал решение, и я дождался использования решения @Chad 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; } 

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

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

 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 использует хвостовую рекурсию или нет …