2020/01/28
フラッシュメッセージを含めたアカウントロック実装方法(gem Sorceryを使用)
- 投稿者
- 米村
こんにちは!開発部の米村です。
クライアントとお話する中で、やはり不正ログインによる個人情報漏洩については特に懸念ポイントであると感じる今日このごろ。
対策方法としては、「特定回数ログインに失敗した場合は、一定時間アカウントをロックする」 というアカウントロックが挙げられますね。
今回は、gem Sorceryを使って、アカウントロック機能が簡単に実装できることを紹介します!
Sorcery 公式Githubの「Brute force protection」をベースとし、ロックの有無によるフラッシュメッセージの切り替えもしていきます!
参考記事: Brute force protection
前提条件
下記のSorcery 公式Githubの通り、ログイン認証機能が実装されていることを前提とさせていただきます。
参考記事: Simple Password Authentication
実装
1.「Brute force protection」の設定追加
下記3つを修正しましょう。
# config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:brute_force_protection]
## submodulesにbrute_force_protectionを追加し、この機能を使用できるよう設定追加。
user.consecutive_login_retries_amount_limit = 5
## 何回ログインに失敗したら、アカウントをロックするか回数を設定。今回は、5回とします。
user.login_lock_time_period = 3600
## アカウントロックを解除するまでの時間を設定。今回は、60分とします。
2. Usersテーブルにカラムを追加
下記3つのカラムを追加します。
- ridgepoleを使用している場合
# db/users.schema
t.integer "failed_logins_count", default: 0
t.datetime "lock_expires_at"
t.string "unlock_token"
- migrationファイルを使用している場合
# db/migrate/*****_sorcery_brute_force_protection.rb
class SorceryBruteForceProtection < ActiveRecord::Migration
def self.up
add_column :users, :failed_logins_count, :integer, default: 0
add_column :users, :lock_expires_at, :datetime, default: nil
add_column :users, :unlock_token, :string, default: nil
end
def self.down
remove_column :users, :lock_expires_at
remove_column :users, :failed_logins_count
remove_column :users, :unlock_token
end
end
3. 既存のログイン機能にアカウントロック時のフラッシュメッセージを追加
ログイン失敗時の部分で、フラッシュメッセージの条件分けを書くことで、コードが理解しやすくなりましたね。
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def new
@user = User.new
end
def create
if login(user_params[:email], user_params[:password])
return redirect_back_or_to root_path, notice: 'ログインしました。'
end
user = User.find_by(email: user_params[:email])
## アカウントロック時は、loginメソッドがnilを返すので、別途対象のuserを取得する必要があります。
flash.now[:notice] = if user && user.login_locked?
## login_locked? はsorceryのメソッドであり、追加したカラム "failed_logins_count"が、アカウントロック回数に至っているuserであるかどうかを確認できます。
'ご利用のアカウントはロックされています。時間をおいて再度ログインしてください。'
else
'ログインに失敗しました。'
end
render :new
end
private
def user_params
params.require(:user).permit(:email, :password)
end
end
確認方法
実装が成功しているかrailsコンソールで確認したいと思います。確認用に、ロックまでの回数を2回、解除までの時間を1分とします。
# config/initializers/sorcery.rb
user.consecutive_login_retries_amount_limit = 2
user.login_lock_time_period = 60
- パスワードがロックされていない状態(ログインに1回失敗)
- パスワードがロックされている状態(ログインに2回失敗)
フラッシュメッセージが変更されることも確認してくださいね! 以上です!