使用Rails restful方式的Session实现登陆机制

众所周知,网站开发中实现登入登出功能需要借助session技术,本篇文章希望使用Rails提倡的restful的风格,通过建立session的mvc来实现网站的登入登出。

ActiveModel::SecurePassword机制

ActiveModel::SecurePassword是Rails提供的安全密码API,这个API要求你有一个password_digest的attribute,并提供以下验证机制:

  • create对象时必须提供password
  • password的长度小于或者等于72个字符
  • 提供密码验证(使用password_confirmation的attribute)

首先将bcrypt加入到Gemfile中使用has_secure_password:

gem 'bcrypt', '~> 3.1.7'

下面给出在User的Model中的代码示例:

# Schema: User(name:string, password_digest:string)
class User < ActiveRecord::Base
  has_secure_password
end

user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
user.save                                                       # => false, password required
user.password = 'mUc3m00RsqyRe'
user.save                                                       # => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save                                                       # => true
user.authenticate('notright')                                   # => false
user.authenticate('mUc3m00RsqyRe')                              # => user
User.find_by(name: 'david').try(:authenticate, 'notright')      # => false
User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user

在上例中,使用authenticate方法就可以完成对用户密码的验证。

User Model的设置

为User Model来设置validate条件,使用上一节Rails提供的API来实现User的验证。

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation

  attr_accessor :password

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email

end

Session MVC的实现

sessions_controller.rb

# sessions_controller.rb

  def new
    if user_signed_in?
      redirect_to root_url and return
    end
  end

  def create
    if user = User.find_by_email(params[:email])
      if User.authenticate(params[:password]) # auth password
        session[:user_id] = user.id
        back_uri = if params[:back_to].present? # set back_to uri
                    params[:back_to]
                  else
                    root_url
                  end
        redirect_to back_uri
      else
        flash[:error] = _("error_messages.incorrect_credentials")
        render action: :new
      end
    else
      flash[:error] = _("error_messages.not_exist")
      redirect_to login_url
    end
  end

  def destroy
    session.delete(:user_id)
    redirect_to login_url
  end

sessions/new.haml

# sessions/new.haml

%body
  %h2 登入
  = form_tag "login", method: :post do
    .form-group
      = label_tag :email, _('useremail')
      = email_field_tag :email, params[:email], class: "form-control"
    .form-group
      = label_tag :password, _("password")
      = password_field_tag :password, (params[:password] || nil), class: "form-control"
    .form-group
      = hidden_field_tag :back_to, params[:back_to]
      = submit_tag _("title"), cta_params

routes.rb

在此我们指定路由:

get "login" => "sessions#new"
post "login" => "sessions#create"
delete "logout" => "sessions#destroy"

若使用Rails restful的做法,可以使用:

resources :sessions, only: [:new, :create, :destroy]

你可能感兴趣的:(rails)