寝て起きて寝て

プログラミングが出来ない情報系のブログ

Railsでログインページを作る

今回はログインページを作るだけ ユーザー登録とかは作らない

フォーム認証の実装をする

今回使うもの(ないものはgenerateして)

・controller hello_controller (認証後表示させたいページ) login_controller (認証処理を呼び出すController)

・model user.rb 要素は以下のとおり (rails generate scaffold user username:string password:string salt:string email:string dm:boolean roles:string reviews_count:integer)

・view hello/view.html.erb login/index.html.erb

以上が今回の環境

では作っていく

まずはhelloの設定を行う

controller/hello_controller.rb

class HelloController < ApplicationController
    before_action :check_logined, only: :view
    def view
        @msg = 'おはようおはようボンジュール!おはようおはようボンジュール!'
    end
    private
    def check_logined
        if session[:usr] then #←そもそもセッション情報:usrが存在しているのかを見る
            begin    #←存在する場合はusersテーブルを検索し、ユーザー情報を取得
                @usr = User.find(session[:usr])
            rescue ActiveRecord::RecordNotFound #←存在しない場合はセッションを破棄
                reset_session
            end
        end
        unless @usr #←ユーザー情報を取得できない場合ログインページへ(login/index)
            flash[:referer] = request.fullpath #←①
            redirect_to controller: :login, action: :index
        end
    end
end

ここでは def check_loginedでセッションの判別をしている ①って書いてあるのがちょっとわからん参考書には「ログインに成功した場合、もともと要求されたページにリダイレクトできる」 と書いてあるが、成功した場合の処理描くところじゃないよねここ。失敗した時にリダイレクトってことかな・・・?ちょっと後で確認

これあれだねセッションがなかった場合の処理だからこれであってるねすいません

class User < ActiveRecord::Base
  def self.authenticate(username, password)
    usr = find_by(username: username)
    if usr != nil &&
      usr.password == Digest::SHA1.hexdigest(usr.salt + password) then
      usr
    else
      return
    end
  end
end

ここではUserモデルに対して認証するためのクラスメソッドのauthenticateを実装している ここでは別に難しいことはしていない。ただユーザ名をキーにusersテーブルを検索し、取得したユーザ情報のパスワードを引数passwordと比較し 正しかった場合はUserオブジェクトを返し、違う場合はnilを返す。

なおusersテーブルではパスワードを「ソルト値+元のパスワード」の形式でハッシュ化して格納しているので元に戻す必要がある SHA-1ハッシュ化しているので 「Digest::SHA1.hexdigestメソッド」で生成することができる

次に認証ページを作る login/index.html.erb

<p style="color:Red"><%=@error%></p>
<%= form_tag action: :auth do %>
<div class="field">
  <%= label_tag :username, 'ユーザ名'%> :<br>
  <%= text_field_tag :username, '', size: 20 %>
</div>
<div class="field">
  <%=label_tag :password,'パスワード' %> :<br>
  <%=password_field_tag :password,'',size:20 %>
</div>
<!--ログイン後にリダイレクトすべきアクションを隠しフィールドにセット-->
<%= hidden_field_tag :referer, flash[:referer] %>
<%=submit_tag 'ログイン'%>
<%end%>

login_controller.rb

class LoginController < ApplicationController
  #[ログイン]ボタンのクリック時実行されるアクション
  def auth
    #入力値にしたがって認証処理を実行
    usr = User.authenticate(params[:username],params[:password])
    #戻り値(変数usr)の有無で認証の成否を判定
    if usr then
        reset_session
        session[:usr] = usr.id
        redirect_to params[:referer]  #←隠しフィールドにセットした本来の要求ページにリダイレクト
    else
      #失敗した場合はflash[:referer]を再セットし、ログインページを再描画
      flash.now[:referer] = params[:referer]  #←flash.nowで余計なデータを即座に破棄してフラッシュを設定
      @error = 'ユーザ名/パスワードが間違っています'
      render 'index'
    end
  end
end

これでたぶんできるはず

ちなみにログアウトは今回の場合だとセッション情報を破棄してやればいいので login_controller.rbに

def logout
  reset_session   #セッションを破棄
  redirect_to '/' #トップページにリダイレクト
end

と記述してボタンを設置してやればおk