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

У меня есть URL, которые выглядят так:

http://domain.com/object/23/

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

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

Я делаю это с python / SQLAlchemy с базой данных Postgres. Я посмотрел на первичные ключи UUID, но они кажутся значительным ударом по производительности, так как у меня происходит много соединений. Я мог бы также сделать UUID в дополнительном столбце, а затем выполнить все объединения на основе последовательного интегрального первичного ключа.

Большинство таблиц, которым это необходимо, содержат менее 1000 записей. Но в одной таблице будет несколько миллионов записей. Без этой таблицы я бы просто использовал uuid и покончил с этим. Но с тех пор я не думаю, что uuid - отличный выбор.

Реальный вопрос в том, каковы мои другие варианты.

  1. Используйте последовательный числовой первичный ключ, но шифруйте / дешифруйте их на лету, когда они находятся за пределами базы данных, с помощью некоторого легковесного алгоритма

  2. Разделите столбец и используйте хэш sha1 (или другой хеш) в ключе primary_key + secret_key, который создается при создании строк. Затем я мог бы просто найти строку с помощью этого хэша и выполнить все соединения на обычном ПК.

Здесь важнее всего производительность, при этом сохраняется некоторый уровень случайности с низкой вероятностью столкновения. Каковы лучшие варианты для шифрования / дешифрования для # 1 или каков лучший хэш-алгоритм для # 2. Есть ли способ более очевидный, чем любой из этих 2? С несколькими миллионами строк uuid не собирается сильно меня тормозить, и это решение?

Ответы [ 3 ]

2 голосов
/ 30 марта 2011

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

Большинство криптографических шифров работают на 64-битных или более крупных блоках, но в вики PostgreSQL есть пример процедуры PL / pgSQL для «не криптографического» шифра , которая работает с (32-битной) int тип. Отказ от ответственности: я сам не пробовал использовать эту функцию.

Чтобы использовать его для своих первичных ключей, запустите вызов CREATE FUNCTION со страницы вики, а затем в ваших пустых таблицах выполните:

ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);

И вуаля!

pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> select * from foo;
  foo_id   
------------
 1241588087
 1500453386
 1755259484
(4 rows)
1 голос
/ 30 марта 2011

Я бы выбрал что-то вроде вашего варианта 2: например, используйте HMAC с SHA1, чтобы получить хеш-значение, которое можно проверять для каждого запроса, даже не приближаясь к базе данных. Я часто выпускаю «билеты», защищенные от взлома. например,

use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
$id = shift;
print "$id.", substr(hmac_sha1_hex($id, "s3kr1t"), 0, 8), "\n"

И для проверки:

use Digest::HMAC_SHA1 qw(hmac_sha1_hex);
$tkt = shift;
($id,$sum) = ($tkt =~ /(.+)\.([0-9a-f]+)/)
        or die "Invalid tkt (bad format): $tkt\n";
$sum eq substr(hmac_sha1_hex($id, "s3kr1t"), 0, 8)
        or die "Invalid tkt (MAC mismatch): $tkt\n";
print $id, "\n"

Это выдает "билет" из 23.3b30e326 для идентификатора 23.

1 голос
/ 30 марта 2011

Хеширование / шифрование кажется излишним для того, чего вы пытаетесь достичь.Как насчет отдельного столбца, в котором хранится случайное число от 10000 до 99999 (или 100000, 999999 и т. Д.), Тогда ссылки выглядят следующим образом:

http://domain.com/object/23-74938/

, где «74938» - это случайный бит

...