Rails,ruby:SecureRandom.urlsafe_base64需要检查令牌的唯一性吗?

Dan*_*n L 8 ruby random unique ruby-on-rails-4

我需要为存储在我的数据库中的用户提供唯一的令牌.在我生成令牌的那一刻,我在使用它之前在DB中检查它的唯一性.这是我实际需要进行的测试还是我在浪费时间?

我已经查看了SecureRandomRuby 2.0.0 API,它没有说明我是否可以"信任"它的唯一性.

我知道没有任何随机值可以真正"独特",而且可能性有限.但是对于32位的十六进制值,我有信心在我的应用程序中再次遇到相同的值,但是想知道是否有人知道这种情况的"陷阱".

另一个考虑是使用,SecureRandom.uuid但基本上是相同的情况.

# usage
user.password_reset_token = Generator.unique_token_for_user(:password_reset_token)

# Performs DB query to ensure uniqueness
class Generator
  def self.unique_token_for_user(attribute)
    begin
      token = SecureRandom.urlsafe_base64(32)
    end while User.exists?(attribute => token)

    token
  end
end
Run Code Online (Sandbox Code Playgroud)

ste*_*lag 11

SecureRandom.uuid生成uuids.UUID长128位,可以保证跨空间和时间的唯一性.它们的设计与全球独一无二urlsafe_base64.请参阅RFC4122.


tom*_*ave 5

它不能确保唯一性,但是,如svoop所说,您两次获得相同结果的可能性极小。

我的建议是:如果您需要的只是随机,唯一且无法猜测的令牌,并且您没有成千上万的用户,那么不用担心就可以使用它。

如果您绝对需要唯一令牌(例如,有一些法律要求),则将与用户关联的唯一字段(例如,用户电子邮件)和随机盐组合起来,并对结果进行哈希处理。

一个简单的实现是:

require 'securerandom'
require 'digest/md5'


def generate_user_token(user)
  digest(user.email + random_salt)
end


def random_salt
  SecureRandom.urlsafe_base64
end


def digest(string)
  Digest::MD5.hexdigest string
end
Run Code Online (Sandbox Code Playgroud)