在Rails中创建唯一标识符的最佳方法是什么?

164

这是我所使用的内容。令牌不一定需要被听到即可猜测,它更像是一个短网址标识符,我希望保持其短小。我遵循了一些在网上找到的示例,在发生冲突的情况下,我认为下面的代码将重新创建令牌,但我并不确定。虽然这感觉有点粗糙,但我很想看到更好的建议。

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,但由于这些令牌是基于用户在应用程序中的操作自动生成批次的(他们下订单并购买令牌),因此让应用程序抛出错误是不可行的。

我可以考虑在结尾附加另一个字符串(例如基于时间生成的字符串),以减少碰撞的可能性,但我不希望令牌变得太长。

12个回答

1
def generate_token
    self.token = Digest::SHA1.hexdigest("--#{ BCrypt::Engine.generate_salt }--")
end

-1

我认为令牌应该像密码一样处理。因此,它们应该在数据库中进行加密。

我正在做类似于以下方式来为模型生成一个唯一的新令牌:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接