Генерация кода подтверждения для подтверждения по электронной почте

Какие есть способы сгенерировать случайный код подтверждения с помощью PHP, который можно сохранить в БД и использовать для подтверждения по электронной почте? Я не могу в жизни придумать способ сгенерировать уникальный номер, который можно сгенерировать из профиля пользователя. Таким образом, я могу использовать функцию, чтобы сделать число достаточно маленьким, чтобы его можно было включить в URL-адрес (см. ссылка). Помните, что пользователь должен щелкнуть ссылку, чтобы «подтвердить/активировать» свою учетную запись. Если я не умею пользоваться цифрами, у меня нет проблем с использованием и букв, и цифр.

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


person sdot257    schedule 18.01.2010    source источник


Ответы (5)


$random_hash = md5(uniqid(rand(), true));

Это будет 32 уникальных буквенно-цифровых символа. Если вы хотите, чтобы он был короче, просто используйте substr():

$random_hash = substr(md5(uniqid(rand(), true)), 16, 16); // 16 characters long

Альтернативные методы генерации случайных данных включают:

$random_hash = md5(openssl_random_pseudo_bytes(32));
$random_hash = md5(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));

// New in PHP7
$random_hash = bin2hex(random_bytes(32));
person John Conde    schedule 18.01.2010
comment
+1 Красиво и уникально и не основано на пользовательских данных. Тем не менее, я думаю, что самая правая часть uniqid более уникальна, чем левая, поэтому вы, вероятно, захотите использовать -16, 16 для substr. - person John Parker; 18.01.2010
comment
И прежде чем возникнет неизбежный вопрос: вам нужно будет хешировать около 18 000 000 000 000 000 000 элементов, прежде чем вы получите 50% вероятность получить два одинаковых хэша. Это один хэш каждую миллисекунду в течение 584 миллионов лет. Так что да, они будут уникальными. - person BlueRaja - Danny Pflughoeft; 18.01.2010
comment
Ага, спасибо ребята! Этого вместе с запросом хеш-кода и имени пользователя должно быть достаточно, не так ли? - person sdot257; 18.01.2010
comment
Случайность функции openssl_random_pseudo_bytes намного лучше, чем rand(). - person akond; 07.06.2011
comment
@middaparka: Хорошая мысль! Но поскольку substr применяется к хешу (md5), а не к uniqid, в данном случае это не имеет значения. - person Levite; 09.04.2014
comment
Мне нужно больше объяснений о том, почему эти методы будут генерировать уникальную строку. Спасибо :) - person Alston; 03.02.2019

1) Создайте активированное поле в базе данных

2) После регистрации отправляется Email

3) Создайте ссылку для включения в электронную почту, используйте уникальный идентификатор. Это будет выглядеть примерно так

Добро пожаловать Имя пользователя Спасибо за регистрацию.

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

domain.com/register.php?uid=100&activate=1

4) Обновите активированное поле до true

alt text
(источник: jackborn.com)

$email_encrypt = urlencode($email);
$special_string = 'maybeyourcompanynamereversed?';
$hash = md5($email_encrypt.$special_string);

Here is the link that is sent to the email that was provided:

http://yourdoman.com/confirm.php?hash='.$hash.'

The actual link will look something like this:

http://yourdomain.com/confirm.php?hash=00413297cc003c03d0f1ffe1cc8445f8
person streetparade    schedule 18.01.2010
comment
+1 за картинку и за код. Использование БД полезно для отслеживания кодов... и обработки истечения срока действия и т. д. - person scunliffe; 19.01.2010
comment
Но из соображений безопасности вам необходимо удалить записи активации - person indianwebdevil; 12.11.2011
comment
Хорошее пошаговое объяснение, но имейте в виду, что если значение $special_string (или ваш исходный код) известно публично, любой может зарегистрировать любой адрес электронной почты и создать соответствующий хэш. Или другими словами: мог активировать любой адрес электронной почты, не владея им. - person Levite; 09.04.2014
comment
-1 это неполное и не возможное: как вы активируете учетную запись на бэкенде, вы не можете восстановить электронную почту из хэша - person albanx; 06.07.2018

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

Если есть какие-либо опасения по поводу возможности угадывания кода подтверждения (и в этом весь смысл выдачи кода), вы можете использовать более случайный генератор, такой как openssl_random_pseudo_bytes(). Затем вы можете использовать bin2hex(), чтобы превратить его в красивый буквенно-цифровой. Следующее выглядит так же, как ответ Джона Конде, но (предположительно) более случайно и менее угадываемо:

// generate a 16 byte random hex string
$random_hash = bin2hex(openssl_random_pseudo_bytes(16))

Позднее дополнение: Как отмечает Олег Абражаев, если вы хотите убедиться, что ваша система действительно способна генерировать криптографически стойкие случайные значения во время выполнения, openssl_random_pseudo_bytes принимает ссылку на логическое значение, чтобы сообщить об этом. Код из документации phpinspectionsea:

$random = openssl_random_pseudo_bytes(32, $isSourceStrong);
if (false === $isSourceStrong || false === $random) {
    throw new \RuntimeException('IV generation failed');
}

Затем используйте сгенерированное случайное значение, как и раньше:

$random_hash = bin2hex($random)
person Robert    schedule 30.08.2014

Решил, что нужно что-то более надежное и с дополнительным функционалом. Вот что я придумал.

/**
 * Hash Gen 
 * @author Kyle Coots
 * @version    1.0
 * Allow you to create a unique hash with a maximum value of 32.
 * Hash Gen uses phps substr, md5, uniqid, and rand to generate a unique 
 * id or hash and allow you to have some added functionality.
 * 
 * @see subtr()
 * @see md5()
 * @see uniqid()
 * @see rand()
 *  
 * You can also supply a hash to be prefixed or appened
 * to the hash. hash[optional] is by default appened to the hash 
 * unless the param prefix[optional] is set to prefix[true].     
 * 
 * @param start[optional]
 * @param end[optional]
 * @param hash[optional]
 * @param prefix bool[optional]
 * 
 * @return string a unique string max[32] character
 */
function hash_gen($start = null, $end = 0, $hash = FALSE, $prefix = FALSE){

    // start IS set NO hash
    if( isset($start, $end) && ($hash == FALSE) ){

        $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
        $new_hash = $md_hash;

    }else //start IS set WITH hash NOT prefixing
    if( isset($start, $end) && ($hash != FALSE) && ($prefix == FALSE) ){

        $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
        $new_hash = $md_hash.$hash;

    }else //start NOT set WITH hash NOT prefixing 
    if( !isset($start, $end) && ($hash != FALSE) && ($prefix == FALSE) ){

        $md_hash = md5(uniqid(rand(), true));
        $new_hash = $md_hash.$hash;

    }else //start IS set WITH hash IS prefixing 
    if( isset($start, $end) && ($hash != FALSE) && ($prefix == TRUE) ){

        $md_hash = substr(md5(uniqid(rand(), true)), $start, $end);
        $new_hash = $hash.$md_hash;

    }else //start NOT set WITH hash IS prefixing
    if( !isset($start, $end) && ($hash != FALSE) && ($prefix == TRUE) ){

        $md_hash = md5(uniqid(rand(), true));
        $new_hash = $hash.$md_hash;

    }else{

        $new_hash = md5(uniqid(rand(), true));

    }

    return $new_hash;

 } 
person Kyle Coots    schedule 04.03.2013

  private  function generateCodeSecurity()
  {
    list($usec, $sec) = explode(" ", microtime());
    $micro = usec + $sec;

    $hoy = date("Y-m-d");  
    $str = str_replace('-','',$hoy); 

    return  rand($str,  $micro);

  }

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

Использование php-функций:

Rand ();
Microtime ()



$hoy = date("Y-m-d");  
$str = str_replace('-','',$hoy); 

echo $str; 
result date: 20170217



 list($usec, $sec) = explode(" ", microtime());
 $micro = usec + $sec;


echo $micro;
result  micro varaible: 1487340849

Передача параметров в эту функцию:rand ();

 rand($str,  $micro);

и вернуться;

пример:

 list($usec, $sec) = explode(" ", microtime());
    $micro = usec + $sec;

    $hoy = date("Y-m-d");  
    $str = str_replace('-','',$hoy); 

   $finalresult = rand($str,  $micro);

echo $finalresult; 

результат: 1297793555

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

person SPC ANGEL    schedule 16.02.2017
comment
Хотя этот фрагмент кода приветствуется и может оказать некоторую помощь, он был бы значительно улучшен, если бы включал объяснение того, как и почему это решает проблему. Помните, что вы отвечаете на вопрос читателей в будущем, а не только того, кто задает сейчас! Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются. В частности, следует объяснить, что это крайне угадываемо и не подходит для намеченной цели. - person Toby Speight; 16.02.2017