Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does has_secure_password work in my model class?

I'm doing the Rails tutorial by Michael Hartl, and I've come to the point where you simply add:

has_secure_password

to your model class and a bunch of magic happens.

I understand that this method comes from the ActiveModel::SecurePassword module that is included in ActiveRecord::Base, which my model class extends.

What I don't understand is what is going on when I add that one line to my class definition. Can somebody please explain, in as much detail as possible. I really want to understand what is going on and not just throw stuff at my app not knowing how it works.

(If it helps to understand why I'm confused, I come from a Java background and I'm new to Ruby)

like image 308
Christopher Perry Avatar asked Mar 20 '13 03:03

Christopher Perry


People also ask

What is has_secure_password?

has_secure_password is used to encrypt and authenticate passwords using BCrypt . It assumes the model has a column named password_digest.

What is password_digest?

The has_secure_password method encrypts passwords by hashing and salting the passwords and generate 'password_digest'. Please read Wikepedia on how bcrypt works. The has_secure_password method in turn gives you, #authenticate method, which you can use to authenticate passwords.


1 Answers

The easiest way of understanding what anything's doing is to consult the source! In this case, that would be the ActiveModel::SecurePassword documentation. From that, you can see that has_secure_password does this:

def has_secure_password
  # Load bcrypt-ruby only when has_secure_password is used.
  # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library.
  gem 'bcrypt-ruby', '~> 3.0.0'
  require 'bcrypt'

  attr_reader :password

  validates_confirmation_of :password
  validates_presence_of     :password_digest

  include InstanceMethodsOnActivation

  if respond_to?(:attributes_protected_by_default)
    def self.attributes_protected_by_default
      super + ['password_digest']
    end
  end
end

To explain in English, this function:

  1. Loads the bcrypt-ruby Gem and requires bcrypt. bcrypt is a secure hashing function that you can learn more about in Wikipedia.
  2. Adds a read-only attribute to the model called password.
  3. Validates that the password is confirmed by another field, called password_confirmation. In other words, you have to enter the password twice to confirm it.
  4. Ensures that password_digest is present before a model is saved.
  5. Load the instance methods, which in this case are authenticate (which returns true if the password is correct, otherwise false) and password=, which encrypts the passed password into the password_digest attribute.
  6. If the method has attributes that are protected by default, this will also add password_digest to that list of protected attributes. (Thus preventing it from being mass assigned.)

You can learn more at the ActiveModel::SecurePassword documentation and the further documentation on its instance attributes.

like image 94
Veraticus Avatar answered Oct 11 '22 09:10

Veraticus