1. Exploring Rails 3.1 - ActiveModel::SecurePassword

    16 April 2011

    Rails 3.1 will have password encryption baked in via ActiveModel::SecurePassword. Any ActiveModel based model will get this functionality. (ActiveRecord, Mongoid)

    Your model will need a field called password_digest and then you’ll need to activate secure password:

    class User < ActiveRecord::Base
       has_secure_password
    end
    

    You get a few things from this

    • attr_accessor :password
    • confirmation validator on password
    • presence validator on password_digest
    • when password is set password_digest is encrypted using bcrypt-ruby
    • #authenticate takes one argument of an unencrypted password. The unencrypted password will be encrypted and compared to the password_digest. If the two match self is returned. If the match fails false is returned.
    You don’t get any validators on the password accessor. While there is an indirect validator with the presence validator on password_digest this won’t work for your forms. You may want to add one:
    class User < ActiveRecord::Base
      has_secure_password
      validates :password, :presence => { :on => :create }
    end
    

    Now you can authenticate in your controllers like so:

    class ApplicationController
      helper_method :current_user, :user_signed_in?, :user_signed_out?
    
      def current_user
        if session[:user_id]
          @current_user ||= User.find(session[:user_id])
        end
        @current_user
      end
    
      def user_signed_in?
        !!current_user
      end
    
      def user_signed_out?
        !user_signed_in?
      end
    end
    
    class SessionController < ApplicationController
      before_filter :user_signed_in?, :only => [:delete]
    
      def create
        if user = User.find_by_email(params[:user][:email]).try(:authenticate, params[:user][:password])
          session[:user_id] = user.id
          redirect_to root_path # Or whatever you want i.e. redirect_to user
        else
          render :new, :flash => { :error => "bad email/password combination" }
        end
      end
    
      def delete
        session.delete(:user_id)
      end
    end
    

Notes

  1. end-of-lease-cleaning-casuarina reblogged this from bcardarella
  2. figure-skating reblogged this from bcardarella
  3. jonpaullussier reblogged this from bcardarella
  4. danhilltech reblogged this from bcardarella
  5. bcardarella posted this