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

时间:2009-05-06 21:04:11

标签: ruby-on-rails ruby-on-rails-plugins

我正在编写一个rails应用程序,就其本质而言,不需要用户注册,因此无法使用身份验证作为保护记录的常用方法。 (我知道,我知道......)此处的用户信息仅限于电子邮件地址。所以我确实需要一种方法来使我的模型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的帖子'等等...

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

5 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:9)

最好的方法是使用生成V4 UUID(通用唯一标识符)的SecureRandom.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&gt; = 4和PostgreSQL,你可以让它为你生成它们:

create_table :posts, id: :uuid do |t|
  ...
end

答案 2 :(得分:5)

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

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

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

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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

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