Как сделать идентификаторы моделей в Rails непредсказуемыми и случайными - PullRequest
18 голосов
/ 07 мая 2009

Я пишу приложение rails, которое по своей природе НЕ МОЖЕТ требовать от пользователей регистрации, и поэтому не может использовать аутентификацию в качестве обычного средства защиты записей. (Я знаю, я знаю ...) Информация о пользователе здесь ограничена адресами электронной почты. Поэтому мне нужен способ сделать мои идентификаторы моделей непредсказуемыми, чтобы другие идентификаторы не могли быть легко угаданы. (Я знаю, я знаю ...)

Я пытался использовать плагины, такие как uuidtools, для рандомизации идентификаторов при создании записей, например:

require 'uuidtools'
class Post < ActiveRecord::Base 
 def before_create() 
  self.id = OpenSSL::Digest.SHA1.hexdigest(UUID.timestamp_create()) 
 end 
end 

... Сначала это выглядит хорошо, но случаются забавные вещи. ActiveRecord иногда пытается вставить значение 0 в идентификатор, и я получаю ошибки, такие как «не могу найти сообщение с идентификатором = 0» и т. Д ...

У меня закончились идеи. Кто-нибудь может помочь? Спасибо.

Ответы [ 5 ]

19 голосов
/ 03 декабря 2012

В вашей модели сделайте это:

before_create :randomize_id

...

private
def randomize_id
  begin
    self.id = SecureRandom.random_number(1_000_000)
  end while Model.where(id: self.id).exists?
end
9 голосов
/ 08 января 2016

Лучший способ - использовать SecureRandom.uuid, который генерирует UUID V4 (универсальный уникальный идентификатор).

Это практически совершенно случайно и уникально (вероятность столкновения примерно одна на десятки триллионов): https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29

Это должно сделать работу:

class Post < ActiveRecord::Base
 before_create :generate_random_id

 private 
 def generate_random_id
   self.id = SecureRandom.uuid
 end 
end

Или, если вы используете Rails> = 4 и PostgreSQL, вы можете сгенерировать их для вас:

create_table :posts, id: :uuid do |t|
  ...
end
5 голосов
/ 07 мая 2009

Есть плагин, который должен делать то, что вы хотите:

http://codesnipers.com/?q=using-uuid-guid-as-primary-key-in-rails

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

3 голосов
/ 12 июля 2009

Проблема в том, что self.id требует int и OpenSSL :: Digest.SHA1.hexdigest (UUID.timestamp_create ()) возвращает строку с нечисловыми символами, которая может привести к значению '0 'фактически хранится в базе данных

2 голосов
/ 07 мая 2009

Альтернативой является генерация токена или контрольной суммы или чего-либо еще во втором столбце при создании записи, и во всех случаях ваши контроллеры запрашивают объект, используйте Model.find_by_id_and_token.

Затем вы всегда будете генерировать URL-адреса, которые содержат и требуют идентификатор и токен.

...