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

20 ruby-on-rails ruby-on-rails-plugins

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

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

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

......一开始看起来不错,但有趣的事情发生了.ActiveRecord有时会尝试在id中插入一个0值,我会收到错误,例如'找不到id = 0的帖子'等等...

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

s.k*_*ger 20

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

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
Run Code Online (Sandbox Code Playgroud)

  • 只要你的用户不到一百万:P (3认同)
  • 这不是线程安全的 - 我已经看到像这样的解决方案在生产系统中创建重复的条目. (3认同)

ccy*_*lle 10

最好的方法是使用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
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用的是Rails> = 4和PostgreSQL,您可以让它为您生成它们:

create_table :posts, id: :uuid do |t|
  ...
end
Run Code Online (Sandbox Code Playgroud)


run*_*ako 5

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

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

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


kch*_*kch 2

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

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