はじめに
Railsのログイン機構のためのgemとして、devise
を利用している場合も多いですが、今回はセキュリティ要件として、過去に利用したパスワードを設定することができないようにするために、devise_security_extension
を利用して過去に設定したパスワードに対しての制限を行いました。
deviseの設定
まずは簡単にRailsアプリケーションの作成からdeviseの設定を行います。
アプリケーションの作成
$ rails new devise_app
$ cd devise_app/
deviseのインストール
Gemfileに以下を追記します。また今回はパスワード再設定のために、再設定メールをブラウザから確認できるようにletter_opener
のgemもインストールします。
gem 'devise'
gem 'letter_opener'
つづいてbundle install
の実行を行います。
$ bundle install
devise の設定
$ rails g devise:install
Running via Spring preloader in process 34286
create config/initializers/devise.rb
create config/locales/devise.en.yml
===============================================================================
Some setup you must do manually if you haven\'t yet:
1. Ensure you have defined default url options in your environments files. Here
is an example of default_url_options appropriate for a development environment
in config/environments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
In production, :host should be set to the actual host of your application.
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root to: "home#index"
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
4. You can copy Devise views (for customization) to your app by running:
rails g devise:views
===============================================================================
deviseに対しての設定情報が表示されるので、表示を参考に必要な設定を行います。
まずconfig/environments/development.rb
に以下を追記。
Rails.application.configure do
# 追記
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config.action_mailer.delivery_method = :letter_opener
end
次にuser
でdevise 用のモデルを作成して、migrate処理を行います。
$ rails generate devise user
Running via Spring preloader in process 34446
invoke active_record
create db/migrate/20180422061404_devise_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
insert app/models/user.rb
route devise_for :users
$ bundle exec rails db:migrate
== 20180422061404 DeviseCreateUsers: migrating ================================
-- create_table(:users)
-> 0.0025s
-- add_index(:users, :email, {:unique=>true})
-> 0.0007s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0010s
== 20180422061404 DeviseCreateUsers: migrated (0.0043s) =======================
以上からrailsサーバを立ち上げuser/sign_in
でログインフォームの画面が表示されればOKです。
devise_security_extension
devise_security_extensionとは
devise_security_extension
はdeviseに対してエンタープライズのセキュリティ要件として必要になる拡張機能を提供します。
今回、題材にした過去利用のパスワードの設定制限の他にも、パスワードのexpire機能やcaptcha機能などが利用できるようになります。
devise_security_extensionの利用
今回は過去のパスワード制限をするための設定を行なっていきます。
なおGithubのissueに記載があるように、Rails5.1以上の環境はgem指定のみであるとエラーになってしまうため、以下をのようにGemfileに追記します。
gem 'devise_security_extension', git: 'https://github.com/phatworx/devise_security_extension.git'
Gemfileへの追記を行なったらbundle
,generator
とコマンドを実行します。
$ bundle install
$ rails generate devise_security_extension:install
Running via Spring preloader in process 34754
create config/initializers/devise_security_extension.rb
create config/locales/devise.security_extension.en.yml
create config/locales/devise.security_extension.de.yml
create config/locales/devise.security_extension.it.yml
devise_security_extension
にはdeviseに関しての様々な拡張機能が用意されていますが、今回は過去のパスワードの利用を禁止するためにpassword_archivable
の機能のみを利用。
generatorによって取り込んだconfig/initializers/devise_security_extension.rb
ファイルからpassword_archivable
に関しての設定のコメントアウトを外します。これによって過去に使用したパスワードのうち5回分(+現在のパスワード)のパスワードの設定を禁止することができます。
用途によってpassword_archiving_count
の回数を変更すると良いでしょう。
Devise.setup do |config|
# How many passwords to keep in archive
config.password_archiving_count = 5
# Deny old password (true, false, count)
config.deny_old_passwords = true
end
次にパスワードの履歴を保存するためのマイグレーションファイルの作成を行います。
マイグレーションファイルには公式のREADMEに従って定義を行えばOKです。
$ rails g migration create_old_passwords
Running via Spring preloader in process 34823
invoke active_record
create db/migrate/20180422065429_create_old_passwords.rb
class CreateOldPasswords < ActiveRecord::Migration[5.2]
def change
create_table :old_passwords do |t|
t.string :encrypted_password, :null => false
t.string :password_archivable_type, :null => false
t.integer :password_archivable_id, :null => false
t.datetime :created_at
end
add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
end
end
マイグレーションファイルを作成したらDBに対して適用を行う。
$ bundle exec rails db:migrate
== 20180422065429 CreateOldPasswords: migrating ===============================
-- create_table(:old_passwords)
-> 0.0024s
-- add_index(:old_passwords, [:password_archivable_type, :password_archivable_id], {:name=>:index_password_archivable})
-> 0.0006s
== 20180422065429 CreateOldPasswords: migrated (0.0033s) ======================
最後にapp/model/user.rb
テーブルに対して:password_archivable
の設定を行います。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
# :password_archivableを追記
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :password_archivable
end
これで設定は終了なので、サーバを再起動して確認。
過去5回に設定したことのあるパスワードを設定しようとすると、以下のようなエラーメッセージが表示されます。
あとは日本語に対するlocale
ファイルを作成すれば、日本語環境においても問題なく動作させることができます。
最後に
今回にdevise_security_extension
のgemを利用して、deviseに対して過去に設定したパスワードに対しての制限を行いました。
devise_security_extension
では他にも、さまざな拡張機能をdeviseに対して設定できるので、機会があれば利用したいと思います。