Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make model IDs in Rails unpredictable and random

In your model, do this:

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

Best way is to use SecureRandom.uuid that generates a V4 UUID (Universally Unique IDentifier).

It is virtually completely random and unique (collision probability is something like one over tens of trillions) : https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29

This should do the job :

class Post < ActiveRecord::Base
 before_create :generate_random_id

 private 
 def generate_random_id
   self.id = SecureRandom.uuid
 end 
end

Or if you are using Rails >= 4 and PostgreSQL, you can have it generating them for you :

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

The thing that is going wrong here is that self.id requires an int and OpenSSL::Digest.SHA1.hexdigest(UUID.timestamp_create()) returns a string with non-numeric characters which would lead to the value '0' being actually stored in the database


An alternative is to generate a token or checksum or whatever in a second column during record creation, and in all cases your controllers query for an object, use Model.find_by_id_and_token.

You'll then always generate URLs that contain and require both the id and token.