Генератор випадкових рядків PHP


814

Я намагаюся створити рандомізовану рядок у PHP, і я не отримую абсолютно жодного результату з цього:

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

    RandomString();
    echo $randstring;

Що я роблю неправильно?


241
Моє однорядне рішення для генерації коротких рядків - substr (md5 (rand ()), 0, 7); удачі ...
тасманіскі

5
@tasmaniski .. Ваше рішення нормально .. Але його менш рандомізоване! У вашому прикладі кількість випадкових рядків, які можна створити, обмежена розміром цілого числа. (2 ^ 32) на макс. У випадку іншого рішення ви можете генерувати (62 ^ 8) .. У випадку, якщо я хочу більші рядки, то кількість окремих рядків залишається на максимумі 2 ^ 32, але в інше рішення воно збільшується до (62 ^ n) ..
Ману

9
Ви забули додати кожен новий створений символ у рядок. Ви просто перезаписуєте його як є. Повинен бути $ randstring. = $ Символів ..
Спок

3
@CaptainLightning Чи можете ви замінити прийняту відповідь на одну з більш безпечних? :)
Скотт Арчішевський

2
strlen($characters)=> strlen($characters) - 1- довжина рядка починається з 1
Zippp

Відповіді:


1393

Щоб відповісти на це питання конкретно, дві проблеми:

  1. $randstring не в обсягах, коли ви повторюєте це.
  2. Персонажі не об'єднуються в циклі.

Ось фрагмент коду з виправленнями:

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

Виведіть випадкову рядок із викликом нижче:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

Зверніть увагу, що це генерує передбачувані випадкові рядки. Якщо ви хочете створити захищені маркери, дивіться цю відповідь .


34
@FranciscoPresencia, Краще "витратити" зайву змінну, як викликати метод у порівнянні стану циклу.
Rico Sonntag

200
Все це працює, чому б не просто щось подібне substr(str_shuffle(MD5(microtime())), 0, 10);?
SpYk3HH

4
Дякуємо за код, але будь ласка, змініть rand()на mt_rand(). Я використовував свій метод і випробував масу зіткнень з іменами.
Нейт

5
@FranciscoPresencia Ви маєте уявлення про те, наскільки це жахливо неефективно? Ви перевіряєте довжину рядка двічі за ітерацію! Струна всередині циклу повинна зберігатися в кешованій змінній перед входом у цикл.
розробникbmw

4
Це не гарне рішення. Рядки, які це створює, будуть передбачуваними. :(
Скотт Арчішевський

370

Примітка: str_shuffle()внутрішньо використовує rand(), що не підходить для цілей криптографії (наприклад, генерування випадкових паролів). Замість цього ви хочете захистити генератор випадкових чисел . Він також не дозволяє повторювати символи.

Ще один спосіб.

ОНОВЛЕНО (тепер це генерує будь-яку довжину рядка):

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

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

Це воно. :)


64
+1 за найкоротшу відповідь :). Але не найкраща відповідь для кожного випадку використання. Цей код виведе рядки, де кожен символ не з’явиться більше одного разу (тим самим зробивши його слабкішим для нападів грубої сили) і не виведе нічого довше 62 символів.
Девід

17
Не робіть цього, він надзвичайно слабкий. Чим довше ви зробите свою випадкову струну, тим вона буде слабшою.
Abhi Beckert

23
Слабке може бути, але це швидко і просто. Залежно від випадку використання, це добре - я використовував його, тому що мені не знадобився безпека або сила; просто швидке загоряння. Я пишу одиничний тест, і це дає мені відповідне випадкове введення для тестування.
SDC

23
@FranciscoPresencia причина не захищена - це те, що він ніколи не використовує одного і того ж символу двічі. Це робить його жахливим генератором паролів. Будь ласка, всі перестаньте голосувати за це, це абсолютно небезпечно ніколи не використовувати. Оскільки пароль стає довшим, кількість символів, які ви повинні перевірити в грубій силі, скорочується, оскільки ви не переймаєтесь тестуванням жодного раніше використовуваного символу.
Abhi Beckert

8
@FranciscoPresencia: Я підтримую ваші коментарі щодо уникнення використання цього випадкового пароля. Однак я не погоджуюся з тим, що ця відповідь не повинна бути плюсовою. У мене є плюс-one'd для цього варіанту, оскільки це ефективне однолінійне рішення для генерації випадкових рядків (початкова тема цього питання).
bwright

331

Відповідей на це питання дуже багато, але жодна з них не використовує криптографічно безпечного генератора псевдовипадкових чисел (CSPRNG).

Проста, безпечна і правильна відповідь - використовувати RandomLib і не винаходити колесо.

Для тих із вас, хто наполягає на тому, щоб винайти власне рішення, PHP 7.0.0 запропонує random_int()для цього; якщо ви все ще знаходитесь на PHP 5.x, ми написали PHP 5 polyfill для того,random_int() щоб ви могли використовувати новий API ще до оновлення до PHP 7.

Безпечне генерування випадкових цілих чисел у 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)


3
На початку функції додайте $keyspace = str_shuffle($keyspace );для більшої безпеки
Євгеній Дмитрієв

13
Що ви маєте на увазі під "для більшої безпеки"? Ми вже використовуємо захищений генератор випадкових чисел.
Скотт Арчішевський

5
@JGEstiot Створення надійних випадкових рядків вимагає криптографічно захищеної випадковості. Хтось, хто шукає "як генерувати випадкові рядки в PHP", краще обслуговується безпечною відповіддю, ніж небезпечною відповіддю.
Скотт Арчішевський

1
@ Скотт Арчішевський Вам не потрібно створювати криптографічно випадкові рядки щоразу, коли ви створюєте випадкові рядки. Питання полягало у створенні рандомізованих рядків, і це не має нічого спільного з безпекою. Ви припускали, що рядок буде використовуватися в контексті, залежному від безпеки, і ви додасте шар складності, який відходить від основної частини питання.
JG Estiot

45
Використання random_int()замість rand()або mt_rand()не додає ніяких складностей для розробника. У той же час це надає їм більшої безпеки. Люди, які приходять до StackOverflow, шукаючи швидких рішень, можуть не знати, чи потрібна річ, яку вони будують, чи ні. Якщо ми дамо їм відповіді захищених за замовчуванням, вони створюють більш захищений Інтернет, навіть якщо, з точки зору, це зовсім випадково. Чому б ви протистояли цій цілі, для мене загадка.
Скотт Арчішевський

155

Це створює шістнадцятковий рядок довжиною 20 символів:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

У PHP 7 ( random_bytes () ):

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f

Зверніть увагу, що openssl_random_pseudo_bytes()не використовували криптографічно сильний алгоритм до php 5.6. Пов’язана помилка: bugs.php.net/bug.php?id=70014
acidtv

Також зауважте, що найменша струна, яку ви можете зробити, - це довжина 2. Якщо ви перейдете байт довжиною 1 або менше, openssl_random_pseudo_bytes()ви нічого не отримаєте назад. Також зауважте, що при використанні, bin2hex(openssl_random_pseudo_bytes($length / 2))оскільки ви працюєте з цілими числами, він автоматично видалить модуль і використає наступне найменше кратне значення 2. Отже, $length = 19вийде рядок довжиною 18.
Натан Ф.

Пропозиція використовувати його в якості вмісту файлу , який можна відкрити з допомогою fgets($fp, 1024)і кожен редактор файлів , який має проблеми з дуже довгими лініями: function string_rand($len, $split="\n") { return substr(chunk_split(bin2hex(openssl_random_pseudo_bytes(ceil($len / 2))), 1023, $split), 0, $len); }Набір $splitдля nullякщо він повинен повернути одну гільзу. Тим самим ви можете використовувати його для обох випадків.
mgutt

Мені дуже подобається рішення random_bytes для PHP 7, але якщо вам потрібна рядок, яка має певну кількість символів, щось подібне буде працювати? $string = substr(base64_encode(random_bytes($size)), 0, $size);
Programster

Це абсолютно без сумніву найкраще рішення. Займає дуже мало місця і дуже легко зрозуміти.
Меттью Кемпбелл

92

@tasmaniski: ваша відповідь працювала на мене. У мене була така ж проблема, і я б запропонував її тим, хто коли-небудь шукає однакову відповідь. Ось це від @tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>

Ось відео на YouTube, яке показує нам, як створити випадкове число


6
якщо ваша рядок заснована лише на випадковому цілому, чому б просто не використати випадкове ціле число? вони не стають глибшими, пересипаючи його ... і вирізавши хеш, ви насправді знищуєте маленьку ентропію, з якою вам довелося почати.
The Surrican

4
Пам’ятайте, md5це призведе до обмеження до 30 символів і завжди малих символів.
fyrye

3
Крім того, rand () не слід використовувати для криптографії. Якщо ви хочете генерувати криптографічно звуковий рядок, використовуйте openssl_random_pseudo_bytes .
mattkgross

md5(rand())пропонує лише 2 ^ 32 можливі значення. Це означає, що, в середньому, 2 ^ 16 випадкових рядків, ви очікуєте, що один повториться.
Скотт Арчішевський

2
Ну .. я б став би, що ОП не говорить про "надійно випадкові рядки". Це рішення є компактним, легким і досить запам'ятовуваним, для правильних випадків використання. І якщо вам потрібно подбати про можливі зіткнення, то чому б не додати / додати часову позначку до випадкової рядки? :)
Еренор Пас

46

Залежно від вашої програми (я хотів генерувати паролі), ви можете використовувати

$string = base64_encode(openssl_random_pseudo_bytes(30));

Будучи base64, вони можуть містити =або -також запитувані символи. Ви можете створити довший рядок, потім відфільтрувати та обрізати його, щоб видалити їх.

openssl_random_pseudo_bytesвидається, що це рекомендований спосіб генерування належного випадкового числа в php. Чому randне використовується, /dev/randomя не знаю.


2
rand не використовує / dev / urandom, тому що це доступно лише в таких середовищах, як posix, і не є портативним.
MacroMan

3
@MacroMan Але openssl_random_pseudo_bytes() це портативний.
Ja͢ck

Якщо ви хочете викреслити зайві символи base64, спробуйте це: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley

3
Це не так, але я б радив бути обережним у тому, як відкинути небажані символи. Наприклад, подивіться цей запит на тягу на сервері OAuth2 Server PHP ліги .
Скотт Арчішевський

Це одна з найкращих відповідей. Шкода, що у нього немає більшої підтримки. Я б рекомендував редагувати вашу відповідь, щоб краще обробляти небажані символи.
jcuenod

28

Ось простий однолінійний параметр, який генерує справжню випадкову рядок без циклічного циклу або використання бібліотек OpenSSL.

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);

Щоб розбити його, щоб параметри були чіткими

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);

Цей метод працює шляхом випадкового повторення списку символів, потім переміщує комбіновану рядок і повертає вказану кількість символів.

Можна додатково рандомізувати це, рандомізувавши довжину повернутого рядка, замінивши $chrRandomLengthна mt_rand(8, 15)(для випадкової рядки між 8 та 15 символами).


шкода сказати, але коли один геть вибрав символів, його ймовірність виникнення знову не така висока, як інші символи, які все ще залишаються в пулі. тут немає справжньої випадковості ...
The Surrican

@TheSurrican - Ви не помилилися б у цьому твердженні. Усі символи мають однакову ймовірність, використовуючи цей алгоритм, і, таким чином, є справді випадковим. Це забезпечується повторенням рядка chrList $ chrRepeatMax, і магія дійсно відбувається в str_shuffle, що визначає випадковість.
Прем'єр-міністр Краанг

Усі символи з’являться лише один раз, і це дуже схильне до
грубої

@javius ​​Це неправильно. Рядок char дублюється на стільки символів, скільки ви хочете (див. $chrRepeatMaxІ $chrRepeatMin), - таким чином, рядок 10 char може бути (малоймовірно, але можливо) бути "aaaaaaaaaaa".
Прем'єр-міністр Краанг

@SanuelJackson Вибачте, я пропустив коментар. Я поставив у коментарі неправильну відповідь. Ти правий! Я фактично використовував ваш "трюк", але не використовував mt_rand, тому що це марно IMHO. Це не додає ентропії. Щойно використаний const з максимальною довжиною.
venimus

25
function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}

Тада!


Пам’ятайте, що в sha1результаті буде обмежено 40 символів та завжди малі символи.
fyrye

3
рядки sha1 не є випадковими, певні символи будуть зустрічатися частіше, ніж інші. Нерозумно було б використовувати це в тих випадках, коли ви справді хочете випадковості, як для паролів.
Kit Sunde

1
@KitSunde - так, ша не випадково, rand () - випадковий. І ша ідеально добре для того, що тут потрібно. ОП не потребує криптовалютного рівня випадковості.
Давор

@ rant()Як випадковість не має значення, коли ша не розподілено рівномірно. Якщо вибираєте випадковим чином з нерівномірного розподілу, ви отримуєте точно такий же нерівномірний розподіл. Я не виділяю випадковість "криптовалют", якщо це було так, ви не повинні використовувати rand()жодне з них. Потрібно мінімум зусиль, щоб вирватись з рівномірного розподілу, як у прийнятій відповіді, і це так само випадково, як і rand (), що розумно так.
Кіт Сунде

@KitSunde - це зрештою не має різниці. Саме це і є визначення переобладнання та позолочення.
Давор

24

Кращим способом реалізації цієї функції є:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);

mt_randє більш випадковим відповідно до цього та цього в PHP 7. randФункція є псевдонімом mt_rand.


1
Увага: mt_randне генерує криптографічно захищені значення. Для цього слід використовувати PHP7 random_intабо random_bytes.
jchook

18

$randstringв області функцій не те саме, що сфера, де ви її називаєте. Ви повинні призначити повернене значення змінній.

$randstring = RandomString();
echo $randstring;

Або просто безпосередньо перегукуємось із зворотним значенням

echo RandomString();

Також у своїй функції ви маєте невелику помилку. У циклі for потрібно використовувати .=так, щоб кожен символ був доданий до рядка. Використовуючи, =ви заміщаєте його з кожним новим символом, а не додавати.

$randstring .= $characters[rand(0, strlen($characters))];

14

Спочатку ви визначаєте алфавіт, який хочете використовувати:

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

Використання оператора модуля %дасть упереджений вихід. Однак сильний +1 для RandomLib. Не винаходити колесо.
Скотт Арчішевський

1
Так, нова функція random_int () приємна: D
Ja͢ck

11

Короткі методи ..

Ось декілька найкоротших методів для генерування випадкових рядків

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

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

echo str_shuffle(MD5(microtime()));
?>

10

Я перевірив працездатність найпопулярніших функцій там, час, який потрібен для генерування 1'000'000 рядків із 32 символів у моєму полі:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);

Зверніть увагу: важливо не те, як довго це було, але яке повільніше, а яке швидше, щоб ви могли вибрати відповідно до своїх вимог, включаючи готовність до криптографії тощо.

substr () навколо MD5 було додано для точності, якщо вам потрібен рядок, який коротший, ніж 32 символи.

Заради відповіді: рядок не був зв'язаний, а перезаписаний, а результат функції не зберігався.


Я думаю, що найкраща відповідь. Дякую!
NSukonny

10

PHP 7+ Створюйте криптографічно захищені випадкові байти за допомогою функції random_bytes .

$bytes = random_bytes(16);
echo bin2hex($bytes);

Можливий вихід

da821217e61e33ed4b2dd96f8439056c


PHP 5.3+ Згенеруйте псевдовипадкові байти за допомогою функції openssl_random_pseudo_bytes .

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);

Можливий вихід

e2d1254506fbb6cd842cd640333214ad


Кращий варіант використання може бути

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();

Можливий вихід

ba8cc342bdf91143


Це не створить рядок із заданою довжиною
Timberman

@Timberman зараз генеруватиме точну довжину.
Мадан Сапкота,

9

Один дуже швидкий спосіб - зробити щось на кшталт:

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

Це створить випадкову рядок довжиною 10 символів. Звичайно, деякі можуть сказати, що це трохи важче з боку обчислень, але в наш час процесори оптимізовані для виконання алгоритму md5 або sha256 дуже швидко. І звичайно, якщо rand()функція поверне те саме значення, результат буде однаковим, маючи шанс 1/32767 бути однаковим. Якщо проблема полягає в безпеці, то просто змініть rand()наmt_rand()


7
function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}

4
Це не портативно; якщо ви спробуєте запустити це в будь-якому середовищі, яке не є позиційним, це призведе до фатальної помилки.
Bryan Agee


6

Допоміжна функція від Laravel 5 Framework

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}

4
"Не слід вважати достатнім для криптографії тощо". Це слід сильно підкреслити.
Скотт Арчішевський


4

Відредагована версія функції працює чудово, але я знайшов лише одну проблему: Ви використали неправильний символ, щоб укласти $ символи, тому символ 'іноді є частиною генерованої випадкової рядки.

Щоб виправити це, змініть:

$characters = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

до:

$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

Таким чином використовуються лише вкладені символи, і символ 'ніколи не буде частиною генерованої випадкової рядки.


4

Ще один однолінійний, який генерує випадковий рядок з 10 символів з літерами та цифрами. Він створить масив з range(відрегулює другий параметр, щоб задати розмір), циклічно перетвориться на цей масив і призначить випадковий символ ASCII (діапазон 0-9 або az), а потім імпровідує масив, щоб отримати рядок.

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));

Примітка. Це працює лише у PHP 5.3 та пізніших версіях


нарешті справді випадкове рішення, а не якийсь роздутий хеш 32-бітного випадкового цілого чи перетасованого рядка ...
The Surrican

Є лише одне питання: цифри можуть траплятися так само, як символи, що не так випадково, як я хотів би мати його. все одно +1 для найкращого рішення на цій сторінці. налаштувати це і його ідеальне.
The Surrican

налаштувати ... ось так? rand(0, 57-48+122-97)<57-48?...:...? :)
vp_arth

4

Один лайнер.

Це швидко для величезних струн з деякою унікальністю.

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}

md5(rand())це жахливо небезпечний спосіб генерувати випадкове число.
Скотт Арчішевський

1
рядок з довжиною X і деякою унікальністю є наміром. справжня випадковість не є наміром.
Джейкоб Сміт


3

Мені сподобався останній коментар, який використовував openssl_random_pseudo_bytes, але це не було рішенням для мене, оскільки мені все одно довелося видалити символи, які я не хотів, і я не зміг отримати рядки заданої довжини. Ось моє рішення ...

function rndStr($len = 20) {
    $rnd='';
    for($i=0;$i<$len;$i++) {
        do {
            $byte = openssl_random_pseudo_bytes(1);
            $asc = chr(base_convert(substr(bin2hex($byte),0,2),16,10));
        } while(!ctype_alnum($asc));
        $rnd .= $asc;
    }
    return $rnd;
}

3
function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}

3

Ось моє просте рішення в одному рядку, щоб генерувати дружній випадковий пароль, виключаючи символи, подібні до таких, як "1" і "l", "O" і "0", і т.д. ... ось це 5 символів, але ви можете легко змінити, звичайно:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);

Це ідеально підходить для створення випадкових рядків ідентифікатора для дзвінка пізніше jquery. IDK, якщо її хороша практика, але це допомогло мені багато, не використовуючи для, як прийнято відповідь ...
Родріго Зулуага

3

Ось ще одне рішення.

function genRandomString($length = 10)
{
    if($length < 1)
        $length = 1;
    return substr(preg_replace("/[^A-Za-z0-9]/", '', base64_encode(openssl_random_pseudo_bytes($length * 2))), 0, $length);
}

PS. Я використовую PHP 7.2 на Ubuntu.


2

Ще один спосіб генерувати випадкову рядок у PHP :

function RandomString($length) {
    $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 RandomString(6);

2

Ось як я це роблю, щоб отримати справжній унікальний випадковий ключ:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;

Ви можете використовувати час (), оскільки це часова мітка Unix і завжди унікальна порівняно з іншими випадковими згаданими вище. Потім можна згенерувати md5sum цього і взяти потрібну довжину, необхідну вам для згенерованого рядка MD5 . У цьому випадку я використовую 10 символів, і я міг би використовувати довший рядок, якщо хотів би зробити його більш унікальним.

Я сподіваюся, що це допомагає.


2
Звичайно, time()далеко не унікальне: воно повертатиме те саме значення знову і знову, поки не закінчиться поточна секунда. Що насправді дає деяку випадковість, це str_shuffle()- решта коду лише зменшує вибірку для вибору символів.
Альваро Гонсалес

1
так що ви в основному робите - перетасовування навколо 32-бітного цілого числа. Тут не так багато ентропії ...
Сургічний

2
Зловмисник може вгадати значення, яке повертається time()(це лише часова мітка), це слабке джерело випадковості.
AL

2

Параметризований однолінійний, використовуючи лише власні функції 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))))))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.