読者です 読者をやめる 読者になる 読者になる

ボクココ

サービス開発を成功させるまでの歩み

deviseのlockableを後で追加する方法

Rails

ども、@kimihomです。最近アップデートしたMacが文字を打っている途中から変換されるのが全く慣れません。

さて今回は Railsの認証ライブラリの定番、deviseについて。これを利用すると、Userモデルにあらゆる機能をプラグインっぽく追加することができる。

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :registerable,
         :recoverable,
         :rememberable,
         :trackable,
         :validatable
end

さて、こんな状態になっていた時、migration としてスキーマはそれぞれ適切に初期で作成してくれるわけだが、後になってLockableを追加したい時にも対応したいところだ。特にLockableは最初はいらないと思っていても、そのうちセキュリティとか気にしだすと実装したいとなることが多いだろう。そんな対応もdeviseなら簡単にできた。

class AddUserRockableScheme < ActiveRecord::Migration
  def change
      add_column :users, :failed_attempts, :integer, :default => 0 # Only if lock strategy is :failed_attempts
      add_column :users, :unlock_token, :string # Only if unlock strategy is :email or :both
      add_column :users, :locked_at, :datetime
      add_index :users, :unlock_token, :unique => true
  end
end

この最後の index を追加しないと、本番のPostgres環境では失敗が複数回できてしまったりして問題が起きた。必ずインデックスを貼っておこう。

そんでもって、先ほどのUserモデルにlockableを追加し、config/initializers/devise.rb を編集。

  # ==> Configuration for :lockable
  # Defines which strategy will be used to lock an account.
  # :failed_attempts = Locks an account after a number of failed attempts to sign in.
  # :none            = No lock strategy. You should handle locking by yourself.
  config.lock_strategy = :failed_attempts

  # Defines which key will be used when locking and unlocking an account
  config.unlock_keys = [ :email ]

  # Defines which strategy will be used to unlock an account.
  # :email = Sends an unlock link to the user email
  # :time  = Re-enables login after a certain amount of time (see :unlock_in below)
  # :both  = Enables both strategies
  # :none  = No unlock strategy. You should handle unlocking by yourself.
  config.unlock_strategy = :both

  # Number of authentication tries before locking an account if lock_strategy
  # is failed attempts.
  config.maximum_attempts = 5

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

基本的にすべてコメントで説明してくれてるので、特筆すべき点はないが、 both を指定しておけば、1時間待つか、送られてきたメールのリンクをクリックすることで、凍結が解除されるようになる。bothを使うパターンが多いと思う。失敗回数や時間もここで変更が可能。

緊急でアカウントロックを外したい場合

User#unlock_access! が定義されているので、対象ユーザーにこのメソッドを呼べばアカウント凍結が解除される。これも運用時に知っておきたいポイントだ。

終わりに

deviseはユーザー管理の共通事項をあらゆる点で網羅してくれている。本当に素晴らしいgemだと思う。これを他の言語でやったら一々これらを作成しなければならない。

deviseのソースはカオスだが、素直に規約どおりに作れば素晴らしい役割を全うしてくれることだろう。