学びシリーズ第2弾です。
作ってみた機能
BCryptライブラリを使ってログイン画面を実装
環境構成
全体構成・完成イメージ
[DB]TABLE
"managers" ("manager_name" varchar NOT NULL, "hashed_password" varchar NOT NULL)
プログラムコード等
Controller
class SessionsController < ApplicationController def create ss_manager = Manager.authenticate(params[:manager_name], params[:password]) if ss_manager session[:manager_id] = ss_manager.id else flash.alert = "名前とパスワードが一致しません。" end redirect_to :root end def destroy session.delete(:manager_id) redirect_to :root end end
createメソッドでは、画面で入力した名前とパスワードをauthenticateメソッドに渡して、名前とパスワードの一致確認を行います。authenticateメソッドは、後記にも記載しますが、Modelのクラスメソッドです。パスワードの一致確認ができたら、セッションIDを取得します。
destroyメソッドでは、createメソッドで取得したセッションIDを削除しています。
class ApplicationController < ActionController::Base private def current_manager Manager.find_by(id: session[:manager_id]) if session[:manager_id] end helper_method :current_manager end
異なるController間で共通に使用するメソッドは、ApplicationControllerに定義します。
ここでは画面参照時にセッションIDの保有有無を判定するcurrent_managerメソッドを実装しています。画面参照時なので、HelperのようにViewで使いたい&DBへアクセスしたいという要件があるので、ControllerにあるメソッドをHelperのようにViewで使う事ができるhelper_methodを定義します。
Model
class << self def authenticate(name, password) manager = find_by(manager_name: name) if manager && manager.hashed_password.present? && BCrypt::Password.new(manager.hashed_password) == password manager else nil end end end
Modelのクラスメソッドauthenticateです。セッションは、仕組み上Modelを持ちません。
そのため、セッションからDBや外部サービスへアクセスする場合は、Model内にクラスメソッドを定義して、セッション内で使えるようにする必要があります。ここでは名前をキーにDBからパスワードを取得し、そのパスワードをBCryptで復号化して画面で入力したパスワードと一致確認をしています。
ERB
<% if flash.alert %> <p class="alert"><%= flash.alert %></p> <% end %> <%= form_tag :session do %> <table id="login_form"> <tr> <td style="text-align: right">ユーザー名</td> <td><%= text_field_tag "manager_name", "", style: "width: 120px" %></td> </tr> <tr> <td style="text-align: right">パスワード</td> <td><%= password_field_tag "password", "", style: "width: 120px" %></td> </tr> <tr> <td colspan="2" style="text-align: center"> <%= submit_tag "ログイン" %></td> </tr> </table> <% end %> <% if current_manager %> <p class="manager"> <%= current_manager.manager_name %>さん| <%= link_to "ログアウト", :session, method: :delete, data: { confirm: "ログアウトしますか?" } %> </p> <% end %>
form_tag :sessionを定義する事で、submit時にsessions#create(POST)メソッドを呼び出す事ができます。Controllerで定義したhelper_methodのcurrent_managerがここで使われています。セッションIDを保持している場合のみログアウトのリンクが出てくる様になっています。
学んだ事
Webアプリケーションで頻繁に使われるログイン・ログアウトの基本的な実装を学ぶ事ができました。helper_methodの定義方法についても勉強になりました。
次回は、このセッションIDを使ってどんな事ができるのか勉強していきたいと思います。