ROR - Генерация буквенно-цифровой строки для идентификатора БД - PullRequest
4 голосов
/ 07 марта 2012

В нашей БД каждый Person имеет идентификатор, который представляет собой сгенерированную БД, с автоинкрементным целым числом.Теперь мы хотим сгенерировать более удобный для пользователя буквенно-цифровой идентификатор, который может быть открыт для общественности.Что-то вроде номера паспорта.Очевидно, мы не хотим раскрывать идентификатор БД пользователям.Для целей этого вопроса я назову то, что нам нужно сгенерировать, UID.

Примечание : UID не предназначен для замены идентификатора БД.Вы можете думать об UID как о более симпатичной версии идентификатора БД, которую мы можем выдать пользователям.

  • Мне было интересно, может ли этот UID быть функцией идентификатора БД.То есть мы должны быть в состоянии заново сгенерировать тот же UID для данного идентификатора БД.
  • Очевидно, что функция будет принимать «соль» или ключ, в дополнение к идентификатору БД.
  • UID не должен быть последовательным.То есть два соседних идентификатора БД должны генерировать визуально различающиеся идентификаторы UID.
  • Необязательно, чтобы UID был необратимым.То есть, все в порядке, если кто-то изучит UID в течение нескольких дней и сможет выполнить обратный инжиниринг и найти идентификатор БД.Я не думаю, что это принесет нам вред.
  • UID должен содержать только AZ (только заглавные буквы) и 0-9.Ничего больше.И он не должен содержать символов, которые могут быть перепутаны с другими алфавитами или цифрами, такими как 0 и O, l и 1 и так далее.Я предполагаю, что кодировка Crockford Base32 позаботится об этом.
  • UID должен быть фиксированной длины (10 символов), независимо от размера идентификатора DB.Мы могли бы дополнить UID некоторой постоянной строкой, чтобы довести ее до требуемой фиксированной длины.ID БД может вырасти до любого размера.Таким образом, алгоритм не должен иметь никаких таких входных ограничений.

Я думаю, что способ сделать это:

Шаг 1: Хеширование.

Я читал о следующих хеш-функциях:

Хеш возвращает длинную строку.Я прочитал здесь о том, что называется складыванием XOR, чтобы уменьшить длину строки.Но я не смог найти много информации об этом.

Шаг 2: Кодирование.

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

  • Кодировка Crockford Base 32
  • Z-Base32
  • Base36

Я предполагаю, что результатом кодирования будет искомая строка UID.

Шаг 3: Обход коллизий.

  • Чтобы обойти коллизии, мне было интересно, могу ли я сгенерировать случайный ключ во время генерации UID ииспользуйте этот случайный ключ в функции.
  • Я могу сохранить этот случайный ключ в столбце, чтобы мы знали, какой ключ использовался для генерации этого конкретного UID.
  • Перед вставкой вновь сгенерированного UIDв таблицу я бы проверил уникальность, и если проверка не удалась, я могу сгенерировать новый случайный ключ и использовать его для генерации нового UID.Этот шаг может повторяться до тех пор, пока не будет найден уникальный UID для конкретного идентификатора БД.

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

Я собираюсь реализовать это в Ruby On Rails приложении.Поэтому, пожалуйста, примите это во внимание в своих предложениях.

Спасибо.

Обновление

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

Итак, если я уберу это требование, UID по существу станет полностью случайной буквенно-цифровой строкой из 10 символов.Я добавляю ответ, содержащий мой предложенный план выполнения.Если кто-то придет с лучшим планом, я отмечу это как ответ.

Ответы [ 2 ]

2 голосов
/ 09 марта 2012

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

  • Предварительно сгенерировать достаточно большое количество случайных и уникальных десятибуквенных буквенно-цифровых строк. Нет хеширования или кодирования.
  • Храните их в таблице в случайном порядке.
  • При создании пользователя сначала выберите эти строки и назначьте их пользователю.
  • Удалить этот выбранный идентификатор из пула идентификаторов после назначения его пользователю.
  • Когда пул сокращается до небольшого числа, пополняйте пул новыми строками, очевидно, с проверками уникальности. Это может быть сделано в Задержке, инициированной наблюдателем.
  • Причиной предварительной генерации является то, что мы перекладываем всю дорогостоящую проверку уникальности на одноразовую операцию предварительной генерации.
  • При выборе идентификатора из этого пула для нового пользователя уникальность гарантируется. Таким образом, операция создания пользователя (что очень часто) становится быстрой.
0 голосов
/ 08 марта 2012

Будет ли db_id.chr работать на вас?Он взял бы целые числа и сгенерировал бы из них символьную строку.Затем вы можете добавить их инициалы или фамилию или что-то еще.Пример:

user = {:id => 123456, :f_name => "Scott", :l_name => "Shea"}
(user.id.to_s.split(//).map {|x| (x.to_i + 64).chr}).join.downcase + user.l_name.downcase

#result = "abcdefshea"
...