Лучший способ создать уникальный токен в Rails? - PullRequest
150 голосов
/ 16 мая 2011

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

def self.create_token
    random_number = SecureRandom.hex(3)
    "1X#{random_number}"

    while Tracker.find_by_token("1X#{random_number}") != nil
      random_number = SecureRandom.hex(3)
      "1X#{random_number}"
    end
    "1X#{random_number}"
  end

Моя колонка базы данных для токена является уникальным индексом, и я также использую validates_uniqueness_of :token намодели, но поскольку они создаются партиями автоматически на основе действий пользователя в приложении (они по сути размещают заказ и покупают токены), приложение не может выдать ошибку.

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

Ответы [ 11 ]

0 голосов
/ 30 января 2019

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

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

key = ActiveSupport::KeyGenerator
                .new(Devise.secret_key)
                .generate_key("put some random or the name of the key")

loop do
  raw = SecureRandom.urlsafe_base64(nil, false)
  enc = OpenSSL::HMAC.hexdigest('SHA256', key, raw)

  break [raw, enc] unless Model.exist?(token: enc)
end
...