Поколение уникального ключа

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

12
задан Darryl Hein 20 October 2008 в 19:12
поделиться

13 ответов

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

  1. Используйте эффективный генератор GUID - они длинны и не могут быть уменьшены. Если Вы только используете часть, Вы ПЕРЕСТАЛИ РАБОТАТЬ.
  2. По крайней мере, часть числа последовательно сгенерирована прочь единственной последовательности. Можно добавить пух или кодирующий, чтобы заставить его выглядеть менее последовательным. Преимущество, они запускают короткий - недостаток, они требуют единственного источника. Работа вокруг для единственного исходного ограничения должна пронумеровать источники, таким образом, Вы включаете [источник #] + [seq #], и затем каждый источник может генерировать свою собственную последовательность.
  3. Генерируйте их через некоторые другие средства и затем проверьте их по единственной истории ранее сгенерированных значений.

Любой другой метод не гарантируется. Следует иметь в виду, существенно Вы генерируете двоичное число (это - компьютер), но затем можно закодировать его в Шестнадцатеричном, Десятичном, Base64 или списке слов. Выберите кодирование, которое соответствует Вашему использованию. Обычно для вводимых данных пользователя Вы хотите некоторое изменение Base32 (на который Вы намекнули).

Примечание о ГУИДАХ: Они набирают свою силу уникальности от их длины, и метод раньше генерировал их. Что-либо меньше чем 128 битов не безопасно. Вне генерации случайных чисел существуют характеристики, которые входят в GUID для создания ее более уникальной. Следует иметь в виду, что они только практически уникальны, не абсолютно уникальны. Это возможно, хотя практически невозможный, чтобы иметь дубликат.

Обновленное Примечание о ГУИДАХ: Начиная с записи этого я узнал, что много генераторов GUID используют криптографически безопасный генератор случайных чисел (трудный или невозможный предсказать следующее число, сгенерированное, и маловероятное для повторения). Существует на самом деле 5 различных алгоритмов UUID. Алгоритм 4 - то, что Microsoft в настоящее время использует для поколения Windows GUID API. GUID является реализацией Microsoft стандарта UUID.

Обновление: Если Вы хотите 7 - 16 символов затем, необходимо использовать или метод 2 или 3.

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

Даже лучший генератор случайных чисел имеет возможность повторения равного общему размеру случайного числа, которое Вы генерируете. Возьмите четверть, например. Это - абсолютно случайный разрядный генератор, и его разногласия повторения 1 в 2.

Таким образом, все это сводится к Вашему порогу уникальности. У Вас может быть 100%-я уникальность в 8 цифрах для 1,099,511,627,776 чисел при помощи последовательности и затем base32 кодирование его. Любой другой метод, который не включает проверку по сравнению со списком прошлых чисел только, имеет разногласия, равные n/1,099,511,627,776 (где n=number предыдущих чисел генерировал) того, чтобы не быть уникальным.

19
ответ дан 2 December 2019 в 19:00
поделиться

Я обычно делаю случайную подстроку (рандомизируйте, сколько символов между 8 32, или меньше для пользовательского удобства) или MD5 некоторого значения я вошел, или время или некоторая комбинация. Для большей случайности я делаю MD5 прибывшего значения (скажите, что фамилия), связывают это со временем, MD5 это снова, затем берут случайную подстроку. Да, Вы могли получить равные пароли, но не вероятный вообще.

-1
ответ дан 2 December 2019 в 19:00
поделиться

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

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

0
ответ дан 2 December 2019 в 19:00
поделиться

Вы могли бы интересоваться over-the-top-secure реализацией Steve Gibson генератора пароля (никакой источник, но у него есть подробное описание того, как она работает) в https://www.grc.com/passwords.htm.

Сайт создает огромные пароли с 64 символами, но, так как они абсолютно случайны, Вы могли легко взять первые 8 (или однако многие) символы для менее безопасного, но "максимально случайный" пароль.

Править: из Ваших более поздних ответов я вижу, что Вам нужно что-то больше как GUID, чем пароль, таким образом, это, вероятно, не то, что Вы хотите...

0
ответ дан 2 December 2019 в 19:00
поделиться

Можно интересоваться этой статьей, которая занимается той же проблемой: GUID глобально уникальны, но подстроки GUID не.

Цель этого алгоритма состоит в том, чтобы использовать комбинацию времени и местоположения ("пространственно-временные координаты" для фанатов относительности там) как ключ уникальности. Однако хронометрирование не прекрасно, таким образом, существует возможность, что, например, два GUID сгенерированы в быстрой последовательности от той же машины, таким образом, друг близко к другу вовремя, что метка времени была бы тем же. Это - то, где uniquifier входит.

0
ответ дан 2 December 2019 в 19:00
поделиться

Я все еще не вижу, почему пароли должны быть уникальными? Какова оборотная сторона, если у 2 из Ваших пользователей есть тот же пароль?

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

0
ответ дан 2 December 2019 в 19:00
поделиться

Я обычно делаю это как это:

$this->password = '';

for($i=0; $i<10; $i++)
{
    if($i%2 == 0)
        $this->password .= chr(rand(65,90));
    if($i%3 == 0)
        $this->password .= chr(rand(97,122));
    if($i%4 == 0)
        $this->password .= chr(rand(48,57));
}

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

0
ответ дан 2 December 2019 в 19:00
поделиться

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

0
ответ дан 2 December 2019 в 19:00
поделиться

Не пишущий код, моя логика была бы:

Генерируйте случайную строку от любых приемлемых символов, которые Вы любите.
Затем добавьте половину отметки даты (частичные секунды и все) к передней стороне и другой половине в конец (или где-нибудь в середине, если Вы предпочитаете).

Останьтесь ВЕСЕЛЫМИ!
H

0
ответ дан 2 December 2019 в 19:00
поделиться

Любой алгоритм приведет к дубликатам.

Поэтому я мог бы предложить, чтобы Вы использовали свой существующий алгоритм* и просто проверили на дубликаты?

*Небольшое дополнение: Если uniqid() может быть групповым на основе времени, также включать глобальный счетчик, который Вы увеличиваете после каждого вызова. Тем путем что-то отличается даже в ту же микросекунду.

1
ответ дан 2 December 2019 в 19:00
поделиться

Как Frank Kreuger прокомментировал, пойдите с генератором GUID.

Как этот

0
ответ дан 2 December 2019 в 19:00
поделиться

Недавно мне понадобился быстрый и простой случайный уникальный ключ, поэтому я сделал следующее:

$ukey = dechex(time()) . crypt( time() . md5(microtime() + mt_rand(0, 100000)) ); 

Итак, в основном, я получаю время unix в секундах и добавляю случайную строку md5, сгенерированную из time + случайный номер. Не самый лучший, но для низкочастотных запросов неплохо. Это быстро и работает.

Я провел тест, в котором я генерировал тысячи ключей, а затем искал повторы, и при скорости около 800 ключей в секунду повторений не было, так что неплохо. Думаю, это полностью зависит от mt_rand ()

. Я использую его для трекера опросов, где мы получаем скорость отправки около 1000 опросов в минуту ... так что на данный момент (скрещивает пальцы) дубликатов нет. Конечно, скорость не постоянна (мы получаем заявки в определенное время дня), так что это не доказательство неудач и не лучшее решение ... совет использует инкрементное значение как часть ключа (в моем случае я использовал time (), но могло бы быть лучше).

0
ответ дан 2 December 2019 в 19:00
поделиться

Не считая криптографической части, которая не имеет большого отношения к созданию уникального значения, я обычно использую следующее:

function GetUniqueValue()
{
   static $counter = 0; //initalized only 1st time function is called
   return strtr(microtime(), array('.' => '', ' ' => '')) . $counter++;
}

При вызове в одном процессе $counter увеличивается, поэтому значение всегда уникально в одном процессе.

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

0
ответ дан 2 December 2019 в 19:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: