26

私は、その性質上、ユーザーに登録を要求できないため、レコードを保護するための通常の手段として認証を使用できない 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 

...一見良さそうに見えますが、おかしなことが起こります。ActiveRecord が ID に 0 の値を挿入しようとすることがあり、「ID=0 の投稿が見つかりません」などのエラーが発生します...

アイデアが尽きた。誰でも助けることができますか?ありがとう。

4

4 に答える 4

21

モデルで、次のようにします。

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
于 2012-12-03T10:03:20.883 に答える
16

最善の方法はSecureRandom.uuid、V4 UUID (Universally Unique IDentifier) を生成するものを使用することです。

それは事実上完全にランダムでユニークです (衝突確率は数十兆分の 1 のようなものです): 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
于 2016-01-08T14:52:31.080 に答える
3

ここで間違っているのは、self.id が int を必要とし、OpenSSL::Digest.SHA1.hexdigest(UUID.timestamp_create()) が数値以外の文字を含む文字列を返し、値が実際には '0' になることです。データベースに格納

于 2009-07-12T12:32:10.990 に答える
2

別の方法は、レコードの作成中に 2 番目の列にトークンまたはチェックサムなどを生成することです。すべての場合で、コントローラーはオブジェクトを照会し、Model.find_by_id_and_token.

その後、ID とトークンの両方を含み、必要とする URL を常に生成します。

于 2009-05-06T21:14:16.280 に答える