- 更新日: 2016年11月7日
- Devise
RailsでDeviseによるユーザー登録・ログイン認証・認可の機能追加
Ruby on Rails アプリケーションでユーザー管理を行うために、ユーザー登録、認証の Rails プラグイン Dvise をインストールします。
上記公式の devise readme を中心に、実際に作業して必要な部分だけをまとめました。
— 環境 —
Rails 5.0.0.1
Devise 4.2.0
【追記 2016/11/07】
Rails 5.0.0.1 + Devise 4.2.0 という構成の現時点(2016/11/07)での最新バージョン環境で、Rails + Devise によるユーザー認証の実装を試しましたところ、記事公開当初と同様の手順で実装できました。
【追記ここまで】
— 記事初回公開時の環境 —
Rails 4.0.1
Devise 3.2.2
devise の導入手順
Gemfile に devise を追加します。
1 2 3 4 |
$ vim Gemfile gem 'devise' |
bundle install を実行。
1 2 3 |
$ bundle install |
ジェネレータを実行して、devise をインストール。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
$ bundle exec rails generate devise:install 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: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. If you are deploying on Heroku with Rails 3.2 only, you may want to set: config.assets.initialize_on_precompile = false On config/application.rb forcing your application to not access the DB or load models when precompiling your assets. 5. You can copy Devise views (for customization) to your app by running: rails g devise:views =============================================================================== |
続いて devise ジェネレータで、アプリケーションのユーザーのモデルを任意の名前で作成します。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ bundle exec rails generate devise User invoke active_record create db/migrate/20131202090529_devise_create_users.rb create app/models/user.rb invoke rspec create spec/models/user_spec.rb invoke factory_girl create spec/factories/users.rb insert app/models/user.rb route devise_for :users |
User は任意の名前。例えば管理者用のモデルなら Admin などが可能です。このジェネレーターの実行で、モデルとデフォルト・モジュールのセットアップが行われます。また、config/routes.rb に devise controller へのルーティング設定が行われます。
生成されたマイグレーションファイルを確認してみます。
db/migrate/***_devise_create_users.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| ## Database authenticatable t.string :email, :null => false, :default => "" t.string :encrypted_password, :null => false, :default => "" ## Recoverable t.string :reset_password_token t.datetime :reset_password_sent_at ## Rememberable t.datetime :remember_created_at ## Trackable t.integer :sign_in_count, :default => 0, :null => false t.datetime :current_sign_in_at t.datetime :last_sign_in_at t.string :current_sign_in_ip t.string :last_sign_in_ip ## Confirmable # t.string :confirmation_token # t.datetime :confirmed_at # t.datetime :confirmation_sent_at # t.string :unconfirmed_email # Only if using reconfirmable ## Lockable # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts # t.string :unlock_token # Only if unlock strategy is :email or :both # t.datetime :locked_at t.timestamps end add_index :users, :email, :unique => true add_index :users, :reset_password_token, :unique => true # add_index :users, :confirmation_token, :unique => true # add_index :users, :unlock_token, :unique => true end end |
マイグレート実行。
1 2 3 |
$ bundle exec rake db:migrate |
サーバーが起動していたら、ここでサーバーを再起動します。
1 2 3 |
$ bundle exec rails server |
devise のヘルパーメソッド
認証を必要とするコントローラーの before_action で以下のように指定。ユーザーのモデル名が User の場合は以下。これで、ログイン中のユーザーのみに許可できるコントローラー・アクションを指定できます。
1 |
before_action :authenticate_user! |
ユーザーがサインインしているかどうかを検証するメソッド。
1 |
user_signed_in? |
現在サインインしているユーザーを取得。
1 |
current_user |
ユーザーのセッション情報にアクセス。
1 |
user_session |
ユーザーのモデル名が Member であれば、以上のヘルパーメソッドはそれぞれ以下となります。
1 2 3 4 |
before_action :authenticate_member! member_signed_in? current_member member_session |
【追記 2014/04/13】
ユーザーが自分自身以外のページへのアクセスや情報編集を制限するには、別途メソッドを実装して before_action で呼ぶなどの必要があります。Ruby on Rails チュートリアル:実例を使って Rails を学ぼう(9章)の correct_user のようなメソッドです。
1 2 3 4 5 |
private def correct_user @user = User.find(params[:id]) redirect_to(root_path) unless current_user?(@user) end |
correct_user を設定したアクションは、@user と current_user(現在ログイン中のユーザー)が一致しない場合は、root_path へとリダイレクトされる。
あるいは、Github: cancan のような認可・権限管理のプラグインを使う。
【追記ここまで】
ログイン後のリダイレクト先の設定
ユーザーがサインインしたり、アカウント情報をアップデートしたりした後、devise はリダイレクト先を探します。ルーティングが “user resource” の場合、リダイレクト先として user_root_path、それがなければデフォルトで root_path が使われます。したがって以下のルーティングを行う。
config/routes.rb を編集して以下を追加。
1 |
root 'home#index' |
“homge#index” は任意。
上の’home#index’の例の場合で、root_path 用のコントローラーを生成します。
1 2 3 |
$ bundle exec rails generate controller home index |
after_sign_in_path_for と after_sign_out_path_for をリダイレクト用のフックとしてオーバーライドできます。
メーラー用の設定
config/environments/development.rb にメーラー用の設定を行います。
1 2 3 4 5 6 7 8 9 |
config.action_mailer.default_url_options = { :host => 'localhost:3000' } config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => 'smtp.gmail.com', :port => 587, :authentication => :plain, :user_name => 'メールアドレス', :password => 'パスワード' } |
とりあえず動作確認
ビューにフラッシュメッセージを追加。app/views/layouts/application.html.erb を編集します。
1 2 3 4 5 6 |
<% if notice %> <p class="alert alert-notice"><%= notice %></p> <% end %> <% if alert %> <p class="alert alert-error"><%= alert %></p> <% end %> |
以上を、<%= yield %> のすぐ上に追加。
サインアップとログイン用のリンクを追加。app/views/layouts/application.html.erb を編集します。
1 2 3 4 5 6 7 8 9 |
<p class="navbar-text pull-right"> <% if user_signed_in? %> Logged in as <strong><%= current_user.email %></strong>. <%= link_to 'Edit profile', edit_user_registration_path, :class => 'navbar-link' %> | <%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %> <% else %> <%= link_to "Sign up", new_user_registration_path, :class => 'navbar-link' %> | <%= link_to "Login", new_user_session_path, :class => 'navbar-link' %> <% end %> |
以上を、body のすぐ下に追加。
devise がサインアップ・サインイン・サインアウトなどに関するコードやルーティングを生成してくれているので、ここで一旦動作確認を行います。
http://localhost:3000/ にアクセスして Sign up をクリックします。http://localhost:3000/users/sign_up をブラウザで開いてユーザーを作成します。
ログインやログアウト、Edit profile などの動作を確認します。ログインしていない時に、http://localhost:3000/users/edit ページの表示ができないことを確認。ログインページ(http://localhost:3000/users/sign_in)にリダイレクトされます。
以上で導入〜動作確認までの作業は終了。ものすごく簡単にサインアップ、認証が実装できて驚きです。
以下はさらに詳細な設定などについて。
モデルの設定
devise は10個のモジュールから構成される。
Omniauthable
Confirmable
Recoverable
Registerable
Rememberable
Trackable
Timeoutable
Validatable
Lockable
モデルで利用するモジュールを指定する。
1 |
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches => 20 |
また、:stretches, :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in などいくつかのオプションを指定できる。
Strong Parameters
Rails の認証プラグイン Devise での Strong Parameters について | EasyRamble を参照。
ビューの設定
ビューをカスタマイズするには、まず devise のデフォルトのビューをアプリケーションにコピーします。
1 2 3 |
$ bundle exec rails generate devise:views |
複数のモデル(User と Admin など)を利用する場合、devise はデフォルトでは全てのモデルで同じビューを利用します。個別にビューを作成する場合は、config/initializers/devise.rb で以下を指定します。
1 |
config.scoped_views = true |
その後、個別のビューを作成するには以下を実行。
1 2 3 |
$ bundle exec rails generate devise:views users |
コントローラーの設定
コントローラーもカスタマイズが可能です。以下のように、Devise::SessionsController を継承して、例えば Admins::SessionsController を作成します。
1 2 |
class Admins::SessionsController < Devise::SessionsController end |
app/controller/admins/ ディレクトリにコントローラを作ります。
その後、ルーティングの設定。
1 |
devise_for :admins, :controllers => { :sessions => "admins/sessions" } |
コントローラーを上のように変更した場合、”devise/sessions” のビューは使われないので、”devise/sessions” から “admin/sessions” にビューをコピーします。
devise はフラッシュメッセージを利用するので、以下をビューに追加します。
1 2 |
flash[:notice] flash[:alert] |
ルーティングの設定
ルーティングの設定は、devise_for メソッドを用いる。:class_name, :path_prefix, I18n 用のオプションなどを利用できます。
config/routes.rb で設定。
1 |
devise_for :users |
1 |
devise_for :users, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' } |
もっと詳細にルーティング設定をする場合は、devise_scope メソッドのブロックで指定。
1 2 3 |
devise_scope :user do get "sign_in", :to => "devise/sessions#new" end |
I18n の設定
ロケールファイルで指定する。
1 2 3 4 |
en: devise: sessions: signed_in: 'Signed in successfully.' |
モデルが2つある場合に、単数形のモデル名で分けて、個別にメッセージを指定できます。
1 2 3 4 5 6 7 |
en: devise: sessions: user: signed_in: 'Welcome user, you are signed in.' admin: signed_in: 'Hello admin!' |
devise mailer 用の設定。
1 2 3 4 5 6 7 8 |
en: devise: mailer: confirmation_instructions: subject: 'Hello everybody!' user_subject: 'Hello User! Please confirm your email' reset_password_instructions: subject: 'Reset instructions' |
以下、URLから日本語および各言語のファイルを取得できます。ファイルはdevise.ja.yml。
https://github.com/plataformatec/devise/wiki/I18n
テストヘルパー(RSpec)
RSpec を使う場合、spec/spec_helper.rb か spec/support/devise.rb に以下を記述。
1 2 3 |
RSpec.configure do |config| config.include Devise::TestHelpers, :type => :controller end |
以上の設定で、テストで sign_in, sign_out のメソッドが使えます。
1 2 3 4 5 |
sign_in :user, @user # sign_in(scope, resource) sign_in @user # sign_in(resource) sign_out :user # sign_out(scope) sign_out @user # sign_out(resource) |
注意点が2つ。
2. devise 内部のコントローラーや devise から継承したコントローラーをテストする場合、devise に、リクエストの前にどのマッピングを使うかを教える必要がある。
1 2 |
@request.env["devise.mapping"] = Devise.mappings[:user] get :new |
Omniauth の設定
Rails4 で Devise と OmniAuth で、Twitter/Facebook のOAuth認証と通常フォームでの認証を併用して実装 | EasyRamble を参照。
複数のモデルの設定
User モデルに加えて、Admin モデルを追加したい場合、以下の手順で追加できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Create a migration with the required fields create_table :admins do |t| t.string :email t.string :encrypted_password t.timestamps end # Inside your Admin model devise :database_authenticatable, :timeoutable # Inside your routes devise_for :admins # Inside your protected controller before_filter :authenticate_admin! # Inside your controllers and views admin_signed_in? current_admin admin_session |
代わりに、単純に devise generator を使っても良いです。
注意点としては、それらのモデルは違うルーティングを持ち、サインイン・サインアウト用などのコントローラーも共有できない。コントローラーのアクションを共有して、異なる役割を持たせたい場合、role を使うことを推奨します。role カラムを追加するか、CanCan を使うと可能です。
admin という管理者用カラムを追加する場合。
1 2 3 |
$ bundle exec rails generate migration add_admin_to_users admin:boolean |
以上。Strong Parameters と Omniatuh についてはまた別途書く予定です。
- Devise の関連記事
- RailsのDevise認証機能での実装チェックリストまとめ
- Deviseで送信されるメールのfrom(送信者メールアドレス)を変更
- Facebook の OAuth 認証で OAuthException(191)エラー
- Rails Devise でパスワードリセットなどのメールテンプレート(Mailer ビュー)をカスタマイズ
- Rails + Devise 環境でのフレンドリーフォワーディング機能を修正
- Deviseでユーザー登録完了時にウェルカムメールを送信する
- Rails Devise でユーザーがプロフィール情報を更新後に元のページにリダイレクトさせる
- Devise でユーザーがパスワードなしでアカウント情報を変更するのを許可
- Rails Deviseの日本語化辞書ファイル(devise.ja.yml)
- Rails + Devise で admin ユーザー(管理者)を削除できないようにする
- 初回公開日: 2013年12月2日
Leave Your Message!