ユーザ認証の実装

ログインページの実装を行ってみました。認証の必要なページが要求されるとログインページに遷移、認証に成功すると要求されていたページへ遷移できるというものを実装してみました。また認証のためのUserモデルは先週の記事に書いたものを使用しました。

フォームの入力値を格納するモデル

ログインページのフォームからの入力を受けるためのモデルを実装しました。ユーザ名とパスワードのほか、認証後に実行されるコントローラーパスとアクション名を属性として含みます。

class Form::Login
  
  attr_accessor :next_controller, :next_action, :name, :password
  
  def initialize(controller, action)
    @next_controller = controller
    @next_action = action
    @name = ""
    @password = ""
  end
  
  # リクエストパラメータからの生成
  def self.fromRequestParameters(params)
    params = if params[:login] then params[:login] else params end
    next_controller = 
      if params[:next_controller].blank? then "" else params[:next_controller] end
    next_action = 
      if params[:next_action].blank? then "" else params[:next_action] end
    login = Form::Login.new(next_controller, next_action)
    login.name = if params[:name].blank? then "" else  params[:name] end
    login.password = if params[:password].blank? then  "" else  params[:password] end
    login
  end
  
end

ログインの必要なページへのコントローラへの変更

ログインが必要となるページへ遷移するコントローラに対して前処理のフックメソッドを定義します。

    1. before_filterメソッドはアクションの前処理を行うフックメソッドを追加します。「before_filter :authorize」という記述によりauthorizeというメソッドが各アクションメソッドが実行されるようになります。
    2. フックされるメソッドとなるauthorizeではセッション情報にログイン情報が含まれていなければ、ログインページを表示するアクションへのリダイレクトを行います。このさい、ログインが成功後に、ここで要求されていたアクションが実行できるよう、要求されたコントローラパスとアクション名をリダイレクト先に渡しています。
class Admin::MainteProductController < ApplicationController

  before_filter :authorize
 
  def authorize
    if session['login_user'] == nil then
      redirect_to(url_for(:controller =>'auth', :action => :login,
        :next_controller => controller_path, :next_action => action_name ))
    end
  end

  ...

ログインフォーム

このフォームには、ログインのユーザ名、パスワード名のほか、ログイン成功後にリダイレクトされるべきコントローラーパスとアクション名が引きわたれてためのHiddenフィールドが含まれます。

<div class="cart-form">
  <div>
    <%= flash[:notice] %>
  </div>
  <fieldset>
    <legend>ログインしてください</legend>
    <% form_for (:login, 
        :url => { :action => "authoricate"} )   do |f|   %>
      <%= f.hidden_field :next_controller %>
      <%= f.hidden_field :next_action %>
      <p>
        <label for="name">名前:</label>
        <%= f.text_field :name %>
      </p>
      <p>
        <label for="password">パスワード:</label>
        <%= f.password_field :password %>
      </p>
        <p>
        <%= f.submit "ログイン" %>
      </p>
    <% end %>
  </fieldset>
</div>

認証のコントローラー

    1. loginはログイン入力ページを表示するアクションです。前のページから渡されたパラメータを@login変数に設定するだけです。前のページから渡されたパラメータとは認証後に遷移すべきコントローラパスとアクション名です。
    2. authoricateは、ログインページからサブミットされるアクションです。認証処理を行い、成功すればユーザ情報をセッションに保存し、ログインページ表示前に要求されていたアクションへのリダイレクトを行います。失敗すれば、ログインページを再表示します。
class Admin::AuthController < ApplicationController
  
  def login
    @login = Form::Login.fromRequestParameters(params)
  end
  
  def authoricate
    @login = Form::Login.fromRequestParameters(params)
    if @login.name.blank?
      flash[:notice] = "user is empty."
      return render :action => :login
    end
    user = User.find_by_name(@login.name)
    unless user then
      flash[:notice] = "user #{@login.name} not registed."
      return render :action => :login
    end
    unless user.authoricate(@login.name, @login.password) then
      flash[:notice] = "authotication failed."
      return render :action => :login
    end
    session['login_user'] = user
    redirect_to :controller => @login.next_controller, :action => @login.next_action
  end
    
end