LoginSignup
18
20

More than 5 years have passed since last update.

[rails3, devise] Devise認証のカスタマイズ (Strategies)

Posted at

Devise の認証ロジックをカスタマイズしてみた。
認証ロジックを独自実装する方法を会得すると devise のカスタマイズの幅が大きく広がる。
試作した全ソースコードは https://github.com/katoy/rails-canvas にある。

  1. test を書く
  2. config/initializers/devise.rb で 認証ロジックのメソッドを指定する。
  3. 認証ロジックを実装する。

ここでは、username で login 制限をつけてみた。
user_02, user_04, user_06, user_08 をログイン禁止にする。
(実際にはこんな制限をつけることはないだろうが、ロジックを簡単にする為に。)

$ rake db:fixtures:load
で user_01, user_02, ... を登録できます。
(定義される内容は test/fixtures/user.yml を参照すること)

0. test を書く

user_02 はログインできないこと、 user_01 はログインできること をテストする。

test/integration/devise_test.rb
  ...
  test 'user_02 can not login' do
    post '/users/sign_in', user: { username: 'user_02', password: '123123' }, format: 'js'
    # assert that the response code was status code 401 (unauthorized)
    assert_response 401
  end

  test 'user_01 can login' do
    post '/users/sign_in', user: { username: 'user_01', password: '123123' }
    assert_response :success
  end
  ...

1. 認証ロジックのメソッドを指定する。

以下の行を追加

config/initializers/devise.rb
  ...
require Rails.root.join('app/controllers/local_devise/local_authenticatable')
  ...
  config.warden do |manager|
    manager.default_strategies(:scope => :user).unshift :local_authenticatable
  end
  ...

2. 認証ロジックを実装する。

devise 内にある database での認証ロジックに手を加えた実装をする。

app/controllers/local_devise/local_authenticatable.rb
# -*- coding: utf-8 -*-

require 'devise/strategies/authenticatable'

# See
#  https://github.com/plataformatec/devise/blob/master/lib/devise/strategies/database_authenticatable.rb
#  http://qiita.com/hattorix@github/items/f383afdef336975bd669#2-3

# ログインチェック方法を独自に定義する。
# databas_authenticable を ベースにして、ログイン許可のアカウントチェックを追加する。
# config/initializers/devise.rb 中で、このチェックメソッドをつかうことを設定する必要がある。

module Devise
  module Strategies
    # Devise 標準の DatabaseAuthenticatable に サーバータイプ別のアカウントチェックを追加。
    class LocalAuthenticatable < Authenticatable
      def authenticate!
        resource  = valid_password? && mapping.to.find_for_database_authentication(authentication_hash)
        encrypted = false

        if validate(resource){ encrypted = true; validate_resource(resource) }
          resource.after_database_authentication
          success!(resource)
        end

        mapping.to.new.password = password if !encrypted && Devise.paranoid
        fail(:not_found_in_database) unless resource
      end

      # ログインチェックのロジック
      def validate_resource(resource)

        # user_0[2468]* のユーザーは login 不可にする。
        return false if /user_0[2468]/ =~ resource.username

        # パスワードのチェック
        resource.valid_password?(password)
      end
    end
  end
end
Warden::Strategies.add(:local_authenticatable, Devise::Strategies::LocalAuthenticatable) 

$ rake test でテストを実行する。

18
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
20