我想在Rails 4.0应用中使用User
时自动为has_secure_password
生成密码(注意:这就是为什么没有attr_accessor
)。
我有一个非常简单的User
模型:
class User < ActiveRecord::Base
has_secure_password
validates :email, presence: true
end
我想知道如何在SecureRandom.hex(8)
电话中使用before_save
创建密码。我尝试添加before_save { self.password = SecureRandom.hex(8) }
及其各种版本,但当我尝试将其保存在Rails控制台中时,它表示password
为空。
非常感谢任何帮助!
答案 0 :(得分:0)
请尝试使用before_validation
回调。 before_save
在validate
之后运行,因此您的记录将始终无效。
还要考虑检查是否已设置密码。否则,您可以在每次更改记录时设置一个新的。
的更多信息答案 1 :(得分:0)
回调是一种有用的解决方案,但在您添加所需的复杂层时会使测试变得困难。
另一种方法是创建一个位于&#34;以上&#34;用户。我不认为这是最好的解决方案,但我发现它是有用的。请注意,此类继承自User
类:
# user_with_default_password.rb
class UserWithDefaultPassword < User
def initialize(options = {})
random_password = SecureRandom.hex(8)
options[:password] = random_password
# If creating a user with confirmation requirements
options[:password_confirmation] = random_password
# Call User.new(options)
super(options)
end
end
用法:
user = UserWithDefaultPassword.new() # => user.password = "ajfladfjkf..."
这样做的好处是,您可以测试User和UserWithDefaultPassword,而不会强制通常会降低测试速度的回调。
此外,如果您只想使用User.new()
而不是UserWithDefaultPassword.new()
,则可以创建包含或不包含默认密码的用户。它提供了更大的灵活性和更好的测试。
更新时间:2014-04-21
另外,我建议将用于创建随机密码的代码等提取到一个单独的类中,您可以快速测试(不加载Rails框架)。以下是我最近为完成其中一些简单任务而编写的课程。
#==================================================
# Generates random/unique strings/tokens/IDs
# See: http://ruby-doc.org/stdlib-2.0.0/libdoc/securerandom/rdoc/SecureRandom.html
# See: http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec-signin_success
#==================================================
class Generator
require "securerandom"
# General-purpose encryption using SHA1 instead of bcrypt; faster but LESS SECURE than bcrypt
# (do not use for extremely sensitive data such as passwords)
def self.encrypt(value)
if value.nil? || value.empty?
""
else
Digest::SHA1.hexdigest(value.to_s)
end
end
# Although a UUID would work as an auto-generated password,
# it just seems more appropriate to make the password a random
# string.
def self.random_password
SecureRandom.urlsafe_base64(32)
end
# Used as a random, unique token
def self.uuid
SecureRandom.uuid
end
# Returns random number as string for admin 2-step authentication
def self.verification_code(length)
value = ""
if length.nil? || length.zero?
length = 6
elsif length > 20
length = 20
end
length.times do |num|
value += SecureRandom.random_number(10).to_s
end
value
end
end
用法:Generator.random_password # => "abc123..."
大好处是您可以在不加载Rails框架的情况下测试随机密码的创建,从而节省3-4秒的加载时间。这主要是通过Rails 4.1来解决的,它使用Spring预加载你的应用程序进行测试,但是如果你不在Rails 4.1上(或者使用Spring gem),这是一个更好的解决方案。