Как вы даете своим пользователям уникальный идентификатор без использования первичного ключа в базе данных? - PullRequest
2 голосов
/ 14 февраля 2011

Если у меня 10 000 пользователей, а первичный ключ - это уникальный идентификатор от 1 до 10 000, есть ли способ дать им всем уникальный идентификатор, чтобы исходный первичный ключ нельзя было из него определить?* Например, ссылка на ваш профиль в Facebook или аналогичную будет http://site.com/profile?id=293852

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

А идеи?

Ответы [ 5 ]

2 голосов
/ 14 февраля 2011

Обычно у вас есть два варианта:

  1. Как вы сказали, используйте случайно сгенерированные данные. (Вам нужно только убедиться, что они уникальны, то есть либо достаточно длинны, либо генерировать-проверить-повторить.)
  2. Получите первичный ключ и преобразуйте его «псевдослучайно» во что-то еще, что, по-видимому, не имеет ничего общего с первичным ключом. Преобразование может быть очень простым (если вы хотите просто мягкую защиту), например, new Random(primaryKey).NextInt(), или это может быть довольно сложно, но защищено от атак, например любой тип сохраняющего формат шифрования .

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

2 голосов
/ 14 февраля 2011

По соображениям безопасности настоятельно рекомендуется делать идентификатор не последовательным, чтобы избежать перечисления пользователя в системе. Но 4 миллиарда (я имею в виду 2 ^ 32) слишком малы, чтобы обеспечить недопустимый интервал. Вот почему GUID является более предпочтительным. В зависимости от базы данных (с точки зрения вашей спецификации это похоже на MSSQL) вы можете хранить в полях, подобных guid, в байтовых полях (для MySQL) или в двух отдельных int64.

Чтобы уменьшить размер URL, можно применить кодировку base64, чтобы GUID выглядел короче.

1 голос
/ 05 августа 2011

Как вы генерируете случайные и уникальные идентификаторы - полезный вопрос, но вы, похоже, делаете предположение о , когда генерирует их!

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

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

Например, у меня есть таблица заказов с указанием order_id. Этот идентификатор генерируется на лету, когда пользователь вводит заказ, постепенно 1,2,3 и т. Д. Навсегда. Пользователю не нужно видеть этот внутренний идентификатор.

Тогда у меня есть другая таблица - random_ids с (order_id, random_id). У меня есть подпрограмма, которая запускается каждую ночь, которая предварительно загружает эту таблицу достаточным количеством строк, чтобы покрыть заказы, которые могут быть вставлены в следующие 24 часа. (Если я когда-нибудь получу 10000 заказов за один день, у меня возникнет проблема - но это будет хорошая проблема!)

Этот подход гарантирует уникальность и отводит любую нагрузку обработки от транзакции вставки в пакетную процедуру, где это не влияет на пользователя.

0 голосов
/ 14 февраля 2011

Я использую часть GUID и фактический идентификатор.

В таблице есть уникальный идентификатор типа столбца со значением по умолчанию newid ()

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

Так что для строки # 8659 у меня будет:
IDcolumn = 8659
GUIDcolumn = '{200BAB55-C7D5-4456-AB57-CFF8B7E82A90} '
PROFILECODE =' 200BAB55H8659 '

Я могу найти правильную строку следующим образом:

partGUID=split(PROFILECODE,'H')(0) - gives 200BAB55
realID=split(PROFILECODE,'H')(1) - give 8659
select * from mytable where IDcolumn=8659 and left(GUIDcolumn,8)='200BAB55';

Теоретически синтаксический анализатор SQL должен сначала найти все строки с IDcolumn 8659, а затем проверитьдля GUIDcolumn

Если люди пытаются угадать идентификатор для профиля, они не могут просто изменить одну его часть и добиться успеха.

0 голосов
/ 14 февраля 2011

Что плохого в том, чтобы позволить пользователю видеть первичный ключ?

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

Или, вы можете выбрать огромное число, а затем основать некоторое уравнение вокруг этого.Что-то вроде:

unique = 1000000000 * (-1 * PK)^3

Это означает, что уникальные числа будут удаляться от вашего начального номера по мере увеличения PK, и будут выше или ниже его в зависимости от того, является ли PK нечетным или четным.Чем сложнее вы добавляете к уравнению, тем меньше вероятность того, что оно будет обнаружено, но никогда не будет на 100% полагаться на этот метод, поскольку всегда есть вероятность, что кто-то с ним справится.

...