Немного о компьютере

Php случайное значение. Случайный выбор из массива в PHP. Известный слабый алгоритм генерирования токенов

Случайные числа - это неотъемлемая часть программирования, особенно если это касается систем безопасности. К примеру, криптография основывается на генерации случайных значений, для получения чисел которые невозможно предугадать. Конечно же и в PHP случайные числа играют огромную роль: с помощью них мы можем генерировать токены, соль и другие значения.

Генерация случайных чисел основывается на специальных алгоритмах. Входным параметром, от которого будет отталкиваться алгоритм, может быть как случайное значение, так и заранее определённое.

В этой статье мы поговорим о случайных числах: как они генерируются и где их можно задействовать.

Использование случайных чисел

В PHP случайные числа играют огромную роль, т.к. очень часто используются для различных целей. В основном, они связаны с безопасностью. На их основе генерируются токены CSRF, ключи API, значения для аутентификации, значения для сброса паролей и многое другое. Всё это делается, для того чтобы получаемые значение было невозможно предугадать.

Самые важные примеры применения случайных значений:

  • Генерация соли для криптографии - случайное число соли используется, как правило, для шифрования “в одну сторону”, а также для хэширования паролей. Это случайное значение используется как вектор инициализации в криптографии.
  • Генерация случайных значений, таких как ID сессии - PHP используется для создания огромного количества приложений, где безопасность стоит на первом месте. Многий функционал базируется на работе с сессиями и сгенерированными ID сессий.
  • Генерация токенов для аутентификации, которые практически невозможно предугадать - многие PHP приложения базируются на работе с другими системами через специальные API интерфейсы. Обычно перед использованием API нужно пройти процесс аутентификации. Получать трудно-подбираемые значения для токенов очень сложно. Именно поэтому в данных задачах используются случайные числа.

Генераторы случайных чисел

Случайные числа, использующиеся в случаях, описанных выше, в PHP генерируются псевдо-генераторами. Всего доступно несколько алгоритмов:

    Линейный конгруэнтный метод , при использовании функции lcg_value().

    Вихрь Мерсенна , используется функцией mt_rand().

    Функция rand(), использующая аналогичную функцию в языке Си.

Фактически данные функции возвращают не случайные числа, а числа, распределённые таким образом, что они выглядят как случайные. Последовательность этих чисел зависит от базового случайного числа внутри реализованного алгоритма.

Базовые числа для генераторов

Базовые числа или вектора таких чисел - это наборы данных, которые используются для генерации случайных чисел. Псевдо-генераторы случайных чисел работают, только отталкиваясь от них. Если злоумышленник узнает это базовое число, то в будущем сможет предугадать значения ваших случайных чисел.

В PHP вы можете задать базовые числа двумя способами. Первый - это используя функцию mt_srand() . Этот способ в основном используется при юнит тестах случайного ряда. Второй способ - это предоставление PHP право самому генерировать базовые числа. Начиная с версии 4.2, PHP предоставляет эту возможность. В последствии для генерации случайных чисел будет задействован Вихрь Мерсенна.

PHP генерирует базовое число, в зависимости от операционной системы. На платформах Linux можно воспользоваться функциями mcrypt_create_iv() или openssl_pseudo_random_bytes() в /dev/urandom. Windows предоставляет специальный псевдо-генератор, к которому можно получить доступ через функции openssl_pseudo_random_bytes() и the mcrypt_create_iv().

Итог

Поскольку случайные числа играют огромную роль в построении безопасных веб приложений, то нам нужно больше знать о том, как они работают. Если вы сами захотите генерировать базовые числа для псевдо-генераторов, то убедитесь в надёжности ваших методов.

выбрать элемент (11)

У меня есть массив с именем $ran = array(1,2,3,4);

Мне нужно получить случайное значение из этого массива и сохранить его в переменной, как я могу это сделать?

Answers

Я основываю свой ответ на функции @ ÓlafurWaage. Я попытался использовать его, но столкнулся со справочными проблемами, когда попытался изменить возвращаемый объект. Я обновил его функцию для передачи и возврата по ссылке. Новая функция:

Function &random_value(&$array, $default=null) { $k = mt_rand(0, count($array) - 1); if (isset($array[$k])) { return $array[$k]; } else { return $default; } }

Для получения дополнительной информации см. Мой вопрос в разделе « Передача / Возврат ссылок на объект + изменение объекта» не работает

$value = $array;

Вы можете использовать функцию array_rand для выбора случайного ключа из вашего массива, как показано ниже.

$array = array("one", "two", "three", "four", "five", "six"); echo $array;

или вы можете использовать функции rand и count для выбора случайного индекса.

$array = array("one", "two", "three", "four", "five", "six"); echo $array;

$random = $ran;

Это также полезно, как функция, если вам нужно значение

Function random_value($array, $default=null) { $k = mt_rand(0, count($array) - 1); return isset($array[$k])? $array[$k]: $default; }

Имеет ли ваш выбор какие-либо последствия для безопасности? Если это так, используйте random_int() и array_keys() . (random_bytes() - только PHP 7, но для PHP 5 существует полиполк).

Function random_index(array $source) { $max = count($source) - 1; $r = random_int(0, $max); $k = array_keys($source); return $k[$r]; }

Применение:

$array = [ "apple" => 1234, "boy" => 2345, "cat" => 3456, "dog" => 4567, "echo" => 5678, "fortune" => 6789 ]; $i = random_index($array); var_dump([$i, $array[$i]]);

Function array_random($array, $amount = 1) { $keys = array_rand($array, $amount); if ($amount == 1) { return $array[$keys]; } $results = ; foreach ($keys as $key) { $results = $array[$key]; } return $results; }

Применение:

$items = ["foo", "bar", "baz", "lorem"=>"ipsum"]; array_random($items); // "bar" array_random($items, 2); // ["foo", "ipsum"]

Несколько примечаний:

  • $amount должна быть меньше или равна count($array) .
  • array_rand() не перетасовывает ключи (начиная с PHP 5.2.10, см. ), поэтому выбранные вами элементы всегда будут в оригинальном порядке. При необходимости используйте shuffle() .

edit: Функция Laravel заметно выросла с тех пор, см. Laravel 5.4"s Arr::random() . Вот что-то более сложное, вытекающее из взрослой функции Laravel:

Function array_random($array, $number = null) { $requested = ($number === null) ? 1: $number; $count = count($array); if ($requested > $count) { throw new \RangeException("You requested {$requested} items, but there are only {$count} items available."); } if ($number === null) { return $array; } if ((int) $number === 0) { return ; } $keys = (array) array_rand($array, $number); $results = ; foreach ($keys as $key) { $results = $array[$key]; } return $results; }

Несколько основных моментов:

  • Выбросить исключение, если не хватает доступных предметов
  • array_random($array, 1) возвращает массив из одного элемента (#19826)
  • Значение поддержки «0» для количества элементов (Это просто чисто и просто.

rand(1,N) но исключая array(a,b,c,..)

есть ли уже встроенная функция, которую я не знаю или мне нужно ее реализовать самостоятельно (как?)?

ОБНОВИТЬ

Квалифицированное решение должно обладать золотом, независимо от того, большой или нет размер excluded array .

Нет встроенной функции, но вы можете сделать это:

Function randWithout($from, $to, array $exceptions) { sort($exceptions); // lets us use break; in the foreach reliably $number = rand($from, $to - count($exceptions)); // or mt_rand() foreach ($exceptions as $exception) { if ($number >= $exception) { $number++; // make up for the gap } else /*if ($number < $exception)*/ { break; } } return $number; }

Это не в моей голове, поэтому он может использовать полировку – но по крайней мере вы не можете оказаться в сценарии с бесконечным циклом, даже гипотетически.

Примечание : Функция ломается, если $exceptions исчерпывает ваш диапазон – например, вызов randWithout(1, 2, array(1,2)) или randWithout(1, 2, array(0,1,2,3)) не даст ничего разумного (очевидно), но в этом случае возвращаемое число будет за пределами $from – $to range, поэтому его легко поймать.

Если $exceptions гарантированно будет отсортировано уже, sort($exceptions); могут быть удалены.

Eye-candy : несколько минимальная визуализация алгоритма.

Я не думаю, что есть такая встроенная функция; вам, вероятно, придется самому закодировать его.

Чтобы закодировать это, у вас есть два решения:

  • Используйте цикл, чтобы вызвать rand () или mt_rand (), пока он не вернет правильное значение
    • что означает вызов rand () несколько раз, в худшем случае
    • но это должно работать нормально, если N велико, и у вас нет многих запрещенных значений.
  • Создайте массив, содержащий только правовые значения
    • И используйте array_rand чтобы выбрать одно значение из него
    • который будет работать нормально, если N мало

В зависимости от того, что вам нужно, и почему этот подход может быть интересной альтернативой.

$numbers = array_diff(range(1, N), array(a, b, c)); // Either (not a real answer, but could be useful, depending on your circumstances) shuffle($numbers); // $numbers is now a randomly-sorted array containing all the numbers that interest you // Or: $x = $numbers; // $x is now a random number selected from the set of numbers you"re interested in

Таким образом, если вам не нужно генерировать набор потенциальных чисел каждый раз, но генерирует набор один раз, а затем выбирает кучу случайных чисел из одного и того же набора, это может быть хорошим способом.

Самый простой способ …

Вам нужно вычислить массив пропущенных местоположений, чтобы вы могли выбрать случайную позицию в непрерывном массиве длиной M = N - #of exceptions и легко отобразить ее обратно в исходный массив с отверстиями. Для этого потребуется время и пространство, равные пропущенному массиву. Я не знаю php из отверстия в земле, поэтому простите текстовый пример кода полу-psudo.

  1. Сделайте новый массив Offset той же длины, что и массив Exceptions.
  2. in Offset [i] сохранит первый индекс в воображаемом непустоте массив, который пропустил бы i элементы в исходном массиве.
  3. Теперь выберите случайный элемент. Выберите случайное число, r , в 0..M количество оставшихся элементов.
  4. Найдите i , что Offset[i] <= r < Offest это легко с бинарным поиском
  5. Возврат r + i

Теперь, это всего лишь эскиз, вам нужно будет разобраться с концами массивов, и если что-то индексируется в форме 0 или 1 и во всем этом джазе. Если вы умны, вы можете фактически вычислить массив Offset на лету от оригинала, но это немного менее понятно.

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

$excludedData = array(); // This is your excluded number $maxVal = $this->db->count_all_results("game_pertanyaan"); // Get the maximum number based on my database $randomNum = rand(1, $maxVal); // Make first initiation, I think you can put this directly in the while > in_array paramater, seems working as well, it"s up to you while (in_array($randomNum, $excludedData)) { $randomNum = rand(1, $maxVal); } $randomNum; //Your random number excluding some number you choose

У меня уже спрашивали пару раз, как я делаю случайный вывод цитат у себя на сайте в блоке "Умные цитаты ". Далее мне удалось выяснить, что проблема здесь с непониманием людей, как вывести случайный элемент из массива в PHP . Задача простая, но тем не менее, раз возникают вопросы, то надо на них отвечать.

Сразу приведу код. Допустим, есть массив с набором цитат. И нужно выбрать одну случайную из них и вывести:

$quotes = array(); // Инициализируем пустой массив
$quotes = "Будьте внимательны к своим мыслям, они - начало поступков."; // Первая цитата
$quotes = "Выживает не самый умный или самый сильный, а самый восприимчивый к переменам."; // Вторая цитата
$quotes = "Жизнь - гора: поднимаешься медленно, спускаешься быстро."; // Третья цитата
$quotes = "Люди не хотят быть богатыми, люди хотят быть богаче других."; // Четвёртая цитата
$number = mt_rand(0, count($quotes) - 1); // Берём случайное число от 0 до (длины массива минус 1) включительно
echo $quotes[$number]; // Выводим цитату
?>

Ключевой момент - это получение случайного числа . Всё, что нужно сделать, это задать правильные границы. Если нужно выбрать на всей длине массива случайный элемент, то это от 0 до (длины массива минус 1 ). А далее просто вытащить элемент из массива с полученным случайным индексом .

Что касается задачи с цитатами, то их лучше хранить в базе данных. В принципе, если сайт совсем простой, то можно и в текстовом файле. Но если в базе данных, то лучше использовать RAND() и LIMIT в SQL-запросе , чтобы Вы сразу получали единственную и случайную цитату из базы данных.

Похожие публикации