如何在Rails中使模型ID不可预测和随机

我正在编写一个rails应用程序,就其本质而言,不需要用户注册,因此不能使用身份validation作为保护记录的常用方法。 (我知道,我知道……)此处的用户信息仅限于电子邮件地址。 因此,我确实需要一种方法来使我的模型ID不可预测,以便不能轻易猜到其他ID。 (我知道我知道…)

我已经尝试使用像uuidtools这样的插件来随机创建记录,如下所示:

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

……起初看起来很不错,但有趣的事情发生了。 ActiveRecord有时会尝试在id中插入一个0值,我会收到错误,例如’找不到id = 0的post’等等…

我已经没想完了。 有人可以帮忙吗? 谢谢。

在您的模型中,执行以下操作:

 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 

最好的方法是使用SecureRandom.uuid生成V4 UUID(通用唯一标识符)。

它实际上是完全随机和独特的(碰撞概率类似于几十万亿): 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 

有一个插件可以做你想要的:

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

(所有道歉都要向SO审查员道歉,因为没有粘贴整篇文章。在我的辩护中,它载有链接和格式,需要相当多的努力来复制。更不用说我们将抢夺页面的流量作者和潜在的收入。)

这里出错的是self.id需要一个int和OpenSSL :: Digest.SHA1.hexdigest(UUID.timestamp_create())返回一个带有非数字字符的字符串,这将导致值’0’实际上存储在数据库中

另一种方法是在创建记录期间在第二列中生成令牌或校验和或其他内容,并且在所有情况下,您的控制器都会查询对象,请使用Model.find_by_id_and_token

然后,您将始终生成包含并同时需要id和token的URL。