active_adminにロック機構を導入する

active_adminをインターネットに公開する場合にアカウントロックを設けたいなぁと思った。

いろいろ調べていたらdeviceでアカウントロックを後から追加するの記事がとても参考になりました。
要約するとactive_adminはdeviceという認証フレームワークを使って作らているのでdevice側にあるアカウントロック機構を使えば簡単に実装できるよってことだと思います。

手順は本当に簡単でした。

1. models/admin_user.rbにロック機構(lockableモジュール)を結びつける宣言をする

class AdminUser < ActiveRecord::Base
  devise :database_authenticatable, 
         :recoverable, :rememberable, :trackable, :validatable, 
         :lockable # <= コレ追加

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
  # attr_accessible :title, :body
end

2. config/initializer/device.rbにお好みのアカウントロック仕様を設定する

ログインに5回失敗したら1分間ロックするという仕様の例。

-  # config.unlock_strategy = :both
+  config.unlock_strategy = :time
 
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
-  # config.maximum_attempts = 20
+  config.maximum_attempts = 5

# Time interval to unlock the account if :time is enabled as unlock_strategy.
-  # config.unlock_in = 1.hour
+  config.unlock_in = 1.minute

3. model AdminUserにロック用のスキーマを追加するマイグレーションを作る

class AddLockableColumnsAdminUser < ActiveRecord::Migration
  def change
    add_column :admin_users, :failed_attempts, :integer, :default => 0
    add_column :admin_users, :unlock_token, :string
    add_column :admin_users, :locked_at, :datetime
  end
end

4. マイグレーション実行

$ rake db:migrate

以上でOK。

最初はactive_adminレコードは下記のようになっている。

+-----------------+--------------+-----------+
| failed_attempts | unlock_token | locked_at |
+-----------------+--------------+-----------+
|               0 | NULL         | NULL      |
+-----------------+--------------+-----------+

active_adminのログインに1回失敗するとfailed_attemptsに1加算される。

+-----------------+--------------+-----------+
| failed_attempts | unlock_token | locked_at |
+-----------------+--------------+-----------+
|               1 | NULL         | NULL      |
+-----------------+--------------+-----------+

5回失敗するとlocked_atにロックされた時間が設定されて設定ファイルで指定した1分が経過するまではログインできなくなる。

+-----------------+--------------+---------------------+
| failed_attempts | unlock_token | locked_at           |
+-----------------+--------------+---------------------+
|               6 | NULL         | 2013-02-08 16:22:35 |
+-----------------+--------------+---------------------+

1分経過後再びログインに失敗するとfailed_attemptsがリセットされてlocked_atが再びNULLになります。

+-----------------+--------------+-----------+
| failed_attempts | unlock_token | locked_at |
+-----------------+--------------+-----------+
|               1 | NULL         | NULL      |
+-----------------+--------------+-----------+

ログインに成功するとfaild_attemptsは0にリセットされるようです。

+-----------------+--------------+-----------+
| failed_attempts | unlock_token | locked_at |
+-----------------+--------------+-----------+
|               0 | NULL         | NULL      |
+-----------------+--------------+-----------+

まとめ

active_adminにロック機構をつけるのは簡単でした。