mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Switch Secure Token generation to Base58
Update Secure Token Doc [ci skip]
remove require securerandom, core_ext/securerandom already do that ref 7e006057
This commit is contained in:
parent
b109397711
commit
47316feee0
2 changed files with 8 additions and 32 deletions
|
@ -13,35 +13,25 @@ module ActiveRecord
|
||||||
#
|
#
|
||||||
# user = User.new
|
# user = User.new
|
||||||
# user.save
|
# user.save
|
||||||
# user.token # => "44539a6a59835a4ee9d7b112"
|
# user.token # => "4kUgL2pdQMSCQtjE"
|
||||||
# user.auth_token # => "e2426a93718d1817a43abbaa"
|
# user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
||||||
# user.regenerate_token # => true
|
# user.regenerate_token # => true
|
||||||
# user.regenerate_auth_token # => true
|
# user.regenerate_auth_token # => true
|
||||||
#
|
#
|
||||||
# SecureRandom is used to generate the 24-character unique token, so collisions are highly unlikely.
|
# SecureRandom::base58 is used to generate the 24-character unique token, so collisions are highly unlikely.
|
||||||
# We'll check to see if the generated token has been used already using #exists?, and retry up to 10
|
|
||||||
# times to find another unused token. After that a RuntimeError is raised if the problem persists.
|
|
||||||
#
|
#
|
||||||
# Note that it's still possible to generate a race condition in the database in the same way that
|
# Note that it's still possible to generate a race condition in the database in the same way that
|
||||||
# validates_presence_of can. You're encouraged to add a unique index in the database to deal with
|
# validates_presence_of can. You're encouraged to add a unique index in the database to deal with
|
||||||
# this even more unlikely scenario.
|
# this even more unlikely scenario.
|
||||||
def has_secure_token(attribute = :token)
|
def has_secure_token(attribute = :token)
|
||||||
# Load securerandom only when has_secure_key is used.
|
# Load securerandom only when has_secure_key is used.
|
||||||
require 'securerandom'
|
require 'active_support/core_ext/securerandom'
|
||||||
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(attribute) }
|
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
||||||
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token(attribute)) }
|
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_unique_secure_token(attribute)
|
def generate_unique_secure_token
|
||||||
10.times do |i|
|
SecureRandom.base58(24)
|
||||||
SecureRandom.hex(12).tap do |token|
|
|
||||||
if exists?(attribute => token)
|
|
||||||
raise "Couldn't generate a unique token in 10 attempts!" if i == 9
|
|
||||||
else
|
|
||||||
return token
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,18 +22,4 @@ class SecureTokenTest < ActiveRecord::TestCase
|
||||||
assert_not_equal @user.token, old_token
|
assert_not_equal @user.token, old_token
|
||||||
assert_not_equal @user.auth_token, old_auth_token
|
assert_not_equal @user.auth_token, old_auth_token
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_raise_after_ten_unsuccessful_attempts_to_generate_a_unique_token
|
|
||||||
User.stubs(:exists?).returns(*Array.new(10, true))
|
|
||||||
assert_raises(RuntimeError) do
|
|
||||||
@user.save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_return_unique_token_after_nine_unsuccessful_attempts
|
|
||||||
User.stubs(:exists?).returns(*Array.new(10) { |i| i == 9 ? false : true })
|
|
||||||
@user.save
|
|
||||||
assert_not_nil @user.token
|
|
||||||
assert_not_nil @user.auth_token
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue