PHP: как создать случайную, уникальную, буквенно-цифровую строку?



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



Как я могу создать один из них с помощью PHP?



обновление: только что вспомнил о uniqid(). Это функция PHP, которая генерирует уникальный идентификатор на основе текущего времени в микросекундах. Думаю, я воспользуюсь этим.

1499   24  

24 ответов:

Примечание: это решение не должно использоваться в ситуациях, когда качество ваших случайность может повлиять на безопасность приложения. В частности, rand() и uniqid() не криптографически безопасный генератор случайных чисел!--9-->. Смотрите Скотт для безопасной альтернативы.

Если вам не нужно, чтобы он был абсолютно уникальным с течением времени:

md5(uniqid(rand(), true))

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

md5(uniqid($your_user_login, true))

я просто изучал, как решить эту же проблему, но я также хочу, чтобы моя функция создавала токен, который можно использовать для поиска пароля. Это означает, что мне нужно ограничить способность маркера угадывать. Потому что uniqid основано на времени, и согласно php.net " возвращаемое значение немного отличается от microtime ()",uniqid не соответствует критериям. В PHP рекомендует использовать openssl_random_pseudo_bytes() вместо того, чтобы генерировать криптографически безопасный жетоны.

быстрый, короткий и по существу ответ:

bin2hex(openssl_random_pseudo_bytes($bytes))

который будет генерировать случайную строку буквенно-цифровых символов длиной = $байт * 2. К сожалению, это только алфавит [a-f][0-9], но он работает.


Ниже приведена самая сильная функция, которую я мог бы сделать, которая удовлетворяет критериям (это реализованная версия ответа Эрика).
function crypto_rand_secure($min, $max)
{
    $range = $max - $min;
    if ($range < 1) return $min; // not so random...
    $log = ceil(log($range, 2));
    $bytes = (int) ($log / 8) + 1; // length in bytes
    $bits = (int) $log + 1; // length in bits
    $filter = (int) (1 << $bits) - 1; // set all lower bits to 1
    do {
        $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
        $rnd = $rnd & $filter; // discard irrelevant bits
    } while ($rnd > $range);
    return $min + $rnd;
}

function getToken($length)
{
    $token = "";
    $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
    $codeAlphabet.= "0123456789";
    $max = strlen($codeAlphabet); // edited

    for ($i=0; $i < $length; $i++) {
        $token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
    }

    return $token;
}

crypto_rand_secure($min, $max) работает как капля в замене для rand() или mt_rand. Он использует openssl_random_pseudo_bytes, чтобы помочь создать случайное число между $min и $max.

getToken($length) создает алфавит для использования в маркере, а затем создает строку длины $length.

EDIT: я забыл привести источник - http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322

EDIT (PHP7): С выпуском PHP7, стандартная библиотека теперь имеет две новые функции, которые может заменить/улучшить / упростить функцию crypto_rand_secure выше. random_bytes($length) и random_int($min, $max)

http://php.net/manual/en/function.random-bytes.php

http://php.net/manual/en/function.random-int.php

пример:

function getToken($length){
     $token = "";
     $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     $codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
     $codeAlphabet.= "0123456789";
     $max = strlen($codeAlphabet); // edited

    for ($i=0; $i < $length; $i++) {
        $token .= $codeAlphabet[random_int(0, $max-1)];
    }

    return $token;
}

объектно-ориентированная версия самого популярного решения

Я создал объектно-ориентированное решение, основанное на Скотт'ы ответ:

<?php

namespace Utils;

/**
 * Class RandomStringGenerator
 * @package Utils
 *
 * Solution taken from here:
 * http://stackoverflow.com/a/13733588/1056679
 */
class RandomStringGenerator
{
    /** @var string */
    protected $alphabet;

    /** @var int */
    protected $alphabetLength;


    /**
     * @param string $alphabet
     */
    public function __construct($alphabet = '')
    {
        if ('' !== $alphabet) {
            $this->setAlphabet($alphabet);
        } else {
            $this->setAlphabet(
                  implode(range('a', 'z'))
                . implode(range('A', 'Z'))
                . implode(range(0, 9))
            );
        }
    }

    /**
     * @param string $alphabet
     */
    public function setAlphabet($alphabet)
    {
        $this->alphabet = $alphabet;
        $this->alphabetLength = strlen($alphabet);
    }

    /**
     * @param int $length
     * @return string
     */
    public function generate($length)
    {
        $token = '';

        for ($i = 0; $i < $length; $i++) {
            $randomKey = $this->getRandomInteger(0, $this->alphabetLength);
            $token .= $this->alphabet[$randomKey];
        }

        return $token;
    }

    /**
     * @param int $min
     * @param int $max
     * @return int
     */
    protected function getRandomInteger($min, $max)
    {
        $range = ($max - $min);

        if ($range < 0) {
            // Not so random...
            return $min;
        }

        $log = log($range, 2);

        // Length in bytes.
        $bytes = (int) ($log / 8) + 1;

        // Length in bits.
        $bits = (int) $log + 1;

        // Set all lower bits to 1.
        $filter = (int) (1 << $bits) - 1;

        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));

            // Discard irrelevant bits.
            $rnd = $rnd & $filter;

        } while ($rnd >= $range);

        return ($min + $rnd);
    }
}

использование

<?php

use Utils\RandomStringGenerator;

// Create new instance of generator class.
$generator = new RandomStringGenerator;

// Set token length.
$tokenLength = 32;

// Call method to generate random string.
$token = $generator->generate($tokenLength);

пользовательские алфавит

при необходимости вы можете использовать пользовательский алфавит. Просто передайте строку с поддерживаемыми символами конструктору или сеттеру:

<?php

$customAlphabet = '0123456789ABCDEF';

// Set initial alphabet.
$generator = new RandomStringGenerator($customAlphabet);

// Change alphabet whenever needed.
$generator->setAlphabet($customAlphabet);

вот выходные образцы

SRniGU2sRQb2K1ylXKnWwZr4HrtdRgrM
q1sRUjNq1K9rG905aneFzyD5IcqD4dlC
I0euIWffrURLKCCJZ5PQFcNUCto6cQfD
AKwPJMEM5ytgJyJyGqoD5FQwxv82YvMr
duoRF6gAawNOEQRICnOUNYmStWmOpEgS
sdHUkEn4565AJoTtkc8EqJ6cC4MLEHUx
eVywMdYXczuZmHaJ50nIVQjOidEVkVna
baJGt7cdLDbIxMctLsEBWgAw5BByP5V0
iqT0B2obq3oerbeXkDVLjZrrLheW4d8f
OUQYCny6tj2TYDlTuu1KsnUyaLkeObwa

Я надеюсь, что это поможет кто-то. Ура!

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

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

    for ($i = 0; $i < $length; $i++) {
        $key .= $keys[array_rand($keys)];
    }

    return $key;
}

echo random_string(50);

пример:

zsd16xzv3jsytnp87tk7ygv73k8zmr0ekh6ly7mxaeyeh46oe8

Я опаздываю, но я здесь с некоторыми хорошими исследовательскими данными, основанными на функциях, предоставляемых Скотт. Поэтому я настроил цифровую каплю океана только для этого 5-дневного автоматизированного теста и сохранил сгенерированные уникальные строки в базе данных MySQL.

в этот период я использовал 5 различных длин (5, 10, 15, 20, 50) и +/-0.5 млн записей были вставлены для каждой длины. Во время моего теста только длина 5 сгенерированных +/-3K дубликатов из 0.5 миллионов и остальные длины не создавали никаких дубликатов. Таким образом, мы можем сказать, что если мы используем длину 15 или выше с функциями Скотта, то мы можем генерировать высоконадежные уникальные строки. Вот таблица с данными моих исследований:

enter image description here

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

вы можете использовать UUID (универсальный уникальный идентификатор), его можно использовать для любых целей, от строки аутентификации пользователя до идентификатора платежной транзакции.

UUID-это 16-октетное (128-битное) число. В своей канонической форме UUID представлен 32 шестнадцатеричными цифрами, отображаемыми в пяти группах, разделенных дефисами, в виде 8-4-4-4-12 в общей сложности 36 символов (32 буквенно-цифровых символа и четыре дефиса).

function generate_uuid() {
    return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
        mt_rand( 0, 0xffff ),
        mt_rand( 0, 0x0C2f ) | 0x4000,
        mt_rand( 0, 0x3fff ) | 0x8000,
        mt_rand( 0, 0x2Aff ), mt_rand( 0, 0xffD3 ), mt_rand( 0, 0xff4B )
    );

}

//вызов funtion

$transationID = generate_uuid();

некоторые примеры вывода будут выглядеть так:

E302D66D-87E3-4450-8CB6-17531895BF14
22D288BC-7289-442B-BEEA-286777D559F2
51B4DE29-3B71-4FD2-9E6C-071703E1FF31
3777C8C6-9FF5-4C78-AAA2-08A47F555E81
54B91C72-2CF4-4501-A6E9-02A60DCBAE4C
60F75C7C-1AE3-417B-82C8-14D456542CD7
8DE0168D-01D3-4502-9E59-10D665CEBCB2

надеюсь, что это поможет кому-то в будущем :)

Я использую этот однострочный:

base64_encode(openssl_random_pseudo_bytes(3 * ($length >> 2)));

где length-длина нужной строки (делится на 4, в противном случае она округляется до ближайшего числа, делящегося на 4)

  1. генерировать случайное число с помощью ваше любимое случайное число генератор
  2. умножить и разделить его чтобы получить число, соответствующее числу символов в вашем алфавите кода
  3. получить элемент по этому индексу в ваш кодовый алфавит.
  4. повторите от 1) пока вы не будете иметь длину вы хочу!--3-->

например (в псевдокоде)

int myInt = random(0, numcharacters)
char[] codealphabet = 'ABCDEF12345'
char random = codealphabet[i]
repeat until long enough

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

$randomNum=substr(str_shuffle("0123456789abcdefghijklmnopqrstvwxyz"), 0, 11);

or we can use custom function to generate the random number

 function randomNumber($length){
     $numbers = range(0,9);
     shuffle($numbers);
     for($i = 0;$i < $length;$i++)
        $digits .= $numbers[$i];
     return $digits;
 }

 //generate random number
 $randomNum=randomNumber(11);

вот окончательный уникальный генератор id для вас. сделано мной.

<?php
$d=date ("d");
$m=date ("m");
$y=date ("Y");
$t=time();
$dmt=$d+$m+$y+$t;    
$ran= rand(0,10000000);
$dmtran= $dmt+$ran;
$un=  uniqid();
$dmtun = $dmt.$un;
$mdun = md5($dmtran.$un);
$sort=substr($mdun, 16); // if you want sort length code.

echo $mdun;
?>

вы можете повторить любой " var " для вашего идентификатора, как вам нравится. но $mdun лучше, вы можете заменить md5 на sha1 для лучшего кода, но это будет очень долго, что может вам не понадобиться.

спасибо.

вот что я использую:

md5(time() . rand());    
// Creates something like 0c947c3b1047334f5bb8a3b7adc1d97b

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

  1. $key = md5(rand());
  2. $key = md5(microtime());
function random_string($length = 8) {
    $alphabets = range('A','Z');
    $numbers = range('0','9');
    $additional_characters = array('_','=');
    $final_array = array_merge($alphabets,$numbers,$additional_characters);
       while($length--) {
      $key = array_rand($final_array);

      $password .= $final_array[$key];
                        }
  if (preg_match('/[A-Za-z0-9]/', $password))
    {
     return $password;
    }else{
    return  random_string();
    }

 }

Скотт, да ты сам пишешь и хорошее решение! Спасибо.

Я также должен генерировать уникальный маркер API для каждого моего пользователя. Ниже приведен мой подход, я использовал информацию о пользователе (Userid и имя пользователя):

public function generateUniqueToken($userid, $username){

        $rand = mt_rand(100,999);
    $md5 = md5($userid.'!(&^ 532567_465 ///'.$username);

    $md53 = substr($md5,0,3);
    $md5_remaining = substr($md5,3);

    $md5 = $md53. $rand. $userid. $md5_remaining;

    return $md5;
}

пожалуйста, посмотрите и дайте мне знать, если никаких улучшений я могу сделать. Спасибо

после прочтения предыдущих примеров я придумал следующее:

protected static $nonce_length = 32;

public static function getNonce()
{
    $chars = array();
    for ($i = 0; $i < 10; $i++)
        $chars = array_merge($chars, range(0, 9), range('A', 'Z'));
    shuffle($chars);
    $start = mt_rand(0, count($chars) - self::$nonce_length);
    return substr(join('', $chars), $start, self::$nonce_length);
}

я дублирую 10 раз массив[0-9, A-Z] и перемешиваю элементы, после того как я получаю случайную начальную точку для substr (), чтобы быть более "творческим" :) вы можете добавить [a-z] и другие элементы в массив, дублировать более или менее, быть более творческим, чем я

вот что я использую на одном из моих проектов, он работает и генерирует УНИКАЛЬНЫЙ СЛУЧАЙНЫЙ ТОКЕН:

$timestampz=time();

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


$tokenparta = generateRandomString();


$token = $timestampz*3 . $tokenparta;

echo $token;

обратите внимание, что я умножил метку времени на три, чтобы создать путаницу для тех, кто пользователь может быть интересно, как этот токен генерируется;)

надеюсь, это поможет :)

Я думаю, что это лучший способ использовать.

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

}

?>

выше функция будет генерировать вам случайную строку длиной 11 символов.

мы можем использовать эти две строки кода для создания уникальной строки проверили около 10000000 раз итерации

  $sffledStr= str_shuffle('abscdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_-+');
    $uniqueString = md5(time().$sffledStr);

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

<?php

echo md5(microtime(true).mt_Rand());

выходы :

40a29479ec808ad4bcff288a48a25d5c

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

Это простая функция, которая позволяет генерировать случайные строки, содержащие буквы и цифры (буквенно-цифровой). Вы также можете ограничить длину строки. Эти случайные строки могут быть использованы для различных целей, в том числе: реферальный код, промокод, код купона. Функция опирается на следующие функции PHP: base_convert, sha1, uniqid, mt_rand

function random_code($length)
{
  return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $length);
}

echo random_code(6);

/*sample output
* a7d9e8
* 3klo93
*/

Я считаю, что проблема со всеми существующими идеями заключается в том, что они наверное уникальный, но не наверняка уникальный (как указано в ответе Дариуша Вальчака на loletech). У меня есть решение, которое на самом деле является уникальным. Это требует, чтобы ваш скрипт имел какую-то память. Для меня это база данных SQL. Вы также можете просто написать в файл где-нибудь. Есть две реализации:

Первый метод: есть два поля, а не 1, которые обеспечивают уникальность. Первое поле-это идентификационный номер, который не является случайным, но является уникальным (первый идентификатор-1, второй-2...). Если вы используете SQL, просто определите поле ID со свойством AUTO_INCREMENT. Второе поле не является уникальным, но случайным. Это может быть создано с помощью любого из других методов, которые люди уже упоминали. Идея Скотта была хороша, но md5 удобен и, вероятно, достаточно хорош для большинства целей:

$random_token = md5($_SERVER['HTTP_USER_AGENT'] . time());

Второй метод: в основном та же идея, но изначально выберите максимальное количество строк, которые когда-либо будут созданы. Это может быть просто очень большое число, как триллион. Затем сделайте то же самое, сгенерируйте идентификатор, но обнулите его так, чтобы все идентификаторы имели одинаковое количество цифр. Затем просто объедините идентификатор со случайной строкой. Это будет достаточно случайным для большинства целей, но раздел ID гарантирует, что он также уникален.

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

function rand_code($len)
{
 $min_lenght= 0;
 $max_lenght = 100;
 $bigL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 $smallL = "abcdefghijklmnopqrstuvwxyz";
 $number = "0123456789";
 $bigB = str_shuffle($bigL);
 $smallS = str_shuffle($smallL);
 $numberS = str_shuffle($number);
 $subA = substr($bigB,0,5);
 $subB = substr($bigB,6,5);
 $subC = substr($bigB,10,5);
 $subD = substr($smallS,0,5);
 $subE = substr($smallS,6,5);
 $subF = substr($smallS,10,5);
 $subG = substr($numberS,0,5);
 $subH = substr($numberS,6,5);
 $subI = substr($numberS,10,5);
 $RandCode1 = str_shuffle($subA.$subD.$subB.$subF.$subC.$subE);
 $RandCode2 = str_shuffle($RandCode1);
 $RandCode = $RandCode1.$RandCode2;
 if ($len>$min_lenght && $len<$max_lenght)
 {
 $CodeEX = substr($RandCode,0,$len);
 }
 else
 {
 $CodeEX = $RandCode;
 }
 return $CodeEX;
}

подробнее о генератор случайных кодов в PHP

упрощение кода Scotts выше путем удаления ненужных циклов, которые сильно замедляются и не делают его более безопасным, чем вызов openssl_random_pseudo_bytes только один раз

function crypto_rand_secure($min, $max)
{
 $range = $max - $min;
 if ($range < 1) return $min; // not so random...
 $log = ceil(log($range, 2));
 $bytes = (int) ($log / 8) + 1; // length in bytes
 $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
 return $min + $rnd%$range;
}

function getToken($length)
{
 return bin2hex(openssl_random_pseudo_bytes($length)
}

Comments

    Ничего не найдено.