【Rails】bcryptを使ってログイン機能を実装する方法
「bcrypt」はパスワードを安全に扱うためのgemパッケージです。
今回はそんなbcryptを使い、Railsでログイン機能を実装します。
1. bcryptをインストール
# Use ActiveModel has_secure_passwordgem 'bcrypt', '~> 3.1.7'
Gemfile
の上の箇所のコメントアウトを外します。
bundle install
Bundlerでインストールしてあげます。
2. パスワード用のカラムを追加
bin/rails g migration AddUsers1
まずマイグレーションを生成。今回はUser
にパスワードを設定したいので、User
用のものを指定します。
class AddUsers1 < ActiveRecord::Migration[5.2] def change add_column :users, :password_digest, :string endend
User
テーブルにpassword_digest
というカラムを追加します。パスワードを扱う際にはこの命名にする必要があります。
bin/rails db:migrate
そうしたらマイグレーションを実行してあげます。
You don’t have bcrypt installed ...
もし上のようなエラーが出た場合は、以下の記事を参考にしてください。
ruby/rails-bcrypt-not-installed)
3.「has_secure_password」を記述
class User < ApplicationRecord has_secure_password(省略)
User.rb
にhas_secure_password
を追記します。これはパスワードを扱うためのおまじない的なものだと思ってもらえれば大丈夫です。
これによりpassword
とpassword_confirmation
という2つのカラムがUser
クラスに追加されます。
ちなみにどちらもNOT NULL
かつ同じ値、というバリデーションがデフォルトで設定されます。
4. パスワードを保存
User.create!(<省略>, password: <任意のパスワード>, password_confirmation: <任意のパスワード>)
Railsコンソールで実際に上の2つのカラムの値を指定し、保存できればOK。
5. コントローラーを作成
ログインのためのコントローラーを作ります。
resource :login ,only: [:create, :destroy]
まずroute.rb
に上のように記述してあげます。
bin/rails g controller logins
次にlogins
コントローラーを作ります。
class LoginsController < ApplicationController def create # ログイン user=User.find_by(login_id:params[:login_id]) if user && user&.authenticate(params[:password]) session[:user_id]=user.id flash.alert="ログインに成功しました。" else flash.alert="ログインに失敗しました。" redirect_to("/") end end
def destroy # ログアウト session.delete(:user_id) redirect_to("/") endend
次にLoginsController
にログインとログアウトの処理を実装。
今回は簡易的なものですが、4行目でパスワードが合っているかをチェックし、5行目でセッションデータに値を入れログインを実現しています。
authenticates
メソッドは、引数で指定したパスワードが合っていればモデルオブジェクトを返してくれます。
6. フォームを実装
<%= form_tag :session, id:"login_form" do %> <div> <label>id:</label> <input type="text" name="login_id"> </div>
<div> <label>パスワード</label> <input type="text" name="password"> </div>
<div> <input type="submit" value="ログイン"> </div><%end%>
erb
ファイルにて、LoginsController
で必要なログインIDとパスワードを入力するフォームを実装します。
7. ログイン中のユーザーを取得
class ApplicationController < ActionController::Base private def current_user if session[:user_id] User.find_by(id:session[:user_id]) end end(省略)
ログインユーザー(ログイン状態)を取得するcurrent_user
メソッドをapplication_controller
に実装。これで全てのコントローラーでログイン状態を取得できます。
8. ログイン状態を表示
<%if current_user%> <%="#{current_user.name}さん"%> <%=link_to("ログアウト",:login,method: :delete,data:{confirm:"本当にログアウトしますか?"})%><%end%>
適当なerb
ファイルを作成し、ログインしている場合にユーザー名とログアウトボタンを表示するようにします。
適当なログインIDとパスワードを入力すると⋯
ユーザー名が表示され、無事ログインできました。