Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 71 lines (62 sloc) 2.902 kb
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
1 require 'active_support/core_ext/object/blank'
39b5ea6 David Heinemeier Hansson Switch from SHA2 to BCrypt (easy Windows compatibility is coming shortly...
dhh authored
2 require 'bcrypt'
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
3
4 module ActiveModel
5 module SecurePassword
6 extend ActiveSupport::Concern
7
bd9dc4f David Heinemeier Hansson BCrypt does its own salting, lovely!
dhh authored
8 WEAK_PASSWORDS = %w( password qwerty 123456 )
9
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
10 module ClassMethods
bd9dc4f David Heinemeier Hansson BCrypt does its own salting, lovely!
dhh authored
11 # Adds methods to set and authenticate against a BCrypt password.
12 # This mechanism requires you to have a password_digest attribute.
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
13 #
14 # Validations for presence of password, confirmation of password (using a "password_confirmation" attribute),
bd9dc4f David Heinemeier Hansson BCrypt does its own salting, lovely!
dhh authored
15 # and strength of password (at least 6 chars, not "password", etc) are automatically added.
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
16 # You can add more validations by hand if need be.
17 #
18 # Example using Active Record (which automatically includes ActiveModel::SecurePassword):
19 #
bd9dc4f David Heinemeier Hansson BCrypt does its own salting, lovely!
dhh authored
20 # # Schema: User(name:string, password_digest:string)
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
21 # class User < ActiveRecord::Base
22 # has_secure_password
23 # end
24 #
25 # user = User.new(:name => "david", :password => "secret", :password_confirmation => "nomatch")
26 # user.save # => false, password not long enough
27 # user.password = "mUc3m00RsqyRe"
28 # user.save # => false, confirmation doesn't match
29 # user.password_confirmation = "mUc3m00RsqyRe"
30 # user.save # => true
31 # user.authenticate("notright") # => false
32 # user.authenticate("mUc3m00RsqyRe") # => user
33 # User.find_by_name("david").try(:authenticate, "notright") # => nil
34 # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
35 def has_secure_password
36 attr_reader :password
37 attr_accessor :password_confirmation
38
bd9dc4f David Heinemeier Hansson BCrypt does its own salting, lovely!
dhh authored
39 attr_protected(:password_digest) if respond_to?(:attr_protected)
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
40
41 validates_confirmation_of :password
42 validates_presence_of :password_digest
43 validate :password_must_be_strong
44 end
45 end
46
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
47 # Returns self if the password is correct, otherwise false.
48 def authenticate(unencrypted_password)
49 if BCrypt::Password.new(password_digest) == unencrypted_password
50 self
51 else
52 false
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
53 end
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
54 end
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
55
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
56 # Encrypts the password into the password_digest attribute.
57 def password=(unencrypted_password)
58 @password = unencrypted_password
59 self.password_digest = BCrypt::Password.create(unencrypted_password)
60 end
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
61
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
62 private
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
63
b8f6dd8 José Valim Add missing require and remove extra module.
josevalim authored
64 def password_must_be_strong
65 if password.present?
66 errors.add(:password, "must be longer than 6 characters") unless password.size > 6
67 errors.add(:password, "is too weak and common") if WEAK_PASSWORDS.include?(password)
68 end
bcf4e4f David Heinemeier Hansson Added ActiveRecord::Base#has_secure_password (via ActiveModel::SecurePas...
dhh authored
69 end
70 end
71 end
Something went wrong with that request. Please try again.