この記事は、2015年6月8日現在の翻訳です。
これ以降の変更は対応していません。
Devise
DeviseはWardenベースのRails用認証ソリューションです。
Deviseは以下の特徴があります。
- Rackベース
- Railsエンジンで動作する完全なMVCソリューション
- 同時に複数のモデルでサインイン可能
- 本当に必要なモノだけを使えるようなモジュール方式のコンセプト
次の10のモジュールから構成されています。
- Database Authenticable: ユーザがサインインするための認証パスワードを暗号化しDBに保存します
- Omniauthable: OmniAuthをサポートします
- Confirmable: 確認フロー中にメールを送付し、サインインの際にアカウントが確認済みか否かをチェックします
- Recoverable: パスワードのリセットをし、リセット方法をメールで送付します
- Registerable: 登録プロセスを通してユーザのサインアップを行い、ユーザ情報の編集や削除機能を有します
- Rememberable: ユーザ情報をクッキーに保存するため、トークンを生成・削除します
- Trackable: サインイン回数、サインイン時間、IPアドレスを保存します
- Timeoutable: 特定の時間でセッションの有効期限を切ることができます
- Validatable: emailとパスワードのバリデーションが可能です。これはオプションであり、カスタマイズ可能であるため、独自バリデーション機能を定義できます
- Lockable: サインインに特定の回数失敗したのち、アカウントをロックします。メールもしくは特定の時間ののちアンロック可能です
Information
The Device Wiki
The Devise Wikiには、たくさんの"how to"記事やFAQを含む情報があります。READMEを読んだ後、見に行ってください。
Bug reports
Deviseに問題を発見したら、教えてほしいです。以下のガイドラインを読んだ後、バグレポートをあげてください。
万が一セキュリティ関連のバグを発見した場合は、GitHubのイシュートラッカーを利用しないでください。以下のメールアドレスへ連絡ください。
opensource@plataformatec.com.br
Mailing list
質問、コメントなどは、GitHubイシュートラッカーではなく、Google Groupsを利用してください。
RDocs
DeviseのドキュメントはRDocフォーマットでも利用可能です。
以前のバージョンのRailsでDeviseを利用する必要がある場合は、過去のドキュメントを確認するため、gemをインストールしたのち、"gem server"をコマンドラインで走らせてください。
Example applications
複数のバージョンのRails上でDeviseの各種機能を動作させるデモアプリケーションサンプルをGitHubで入手可能です。
Extensions
コミュティでは、Deviseを高機能にするたくさんのextensionを作成しています。以下のページで入手可能なextensionのリストを閲覧・入手できます。
Contributing
Deviseへの貢献をお待ちしております。以下の概要を確認してください。
変更に対してはテストを書くと思います。テストスイートを走らせる場合は、Deviseのトップディレクトリを行き、"bundle install"および"rake"を実行してください。テストをパスさせるため、システムにはMongoDBサーバ(2.0以上)が必要になります。
Starting with Rails?
もし、Railsアプリケーションの構築が初めての場合は、Deviseはおすすめしません。DeviseはRailsフレームワークを熟知する必要があります。スクラッチで一度シンプルな認証システムを構築することをおすすめします。次の2つのリソースが参考になるでしょう。
Railsと認証の仕組みを理解したのち、Deviseは非常に有用だとわかります
Getting started
Devise 3.0は、Rails 3.2以上で動作します。Gemfileに追加します。
gem 'devise'
bundleコマンドを実行してください。
Deviseをインストールした後、generatorを実行してください。
rails generate devise:install
generatorは、全てのDevise設定オプションのinitializerをインストールします。一度、必ず確認してください。終わったら、generatorを利用してDeviseを好きなモデルに追加してください。
rails generate devise MODEL
MODELはアプリケーションのユーザを表す名前のクラスに書き換えてください(User
であることが多いですが、Admin
かもしれません)。これにより、(もし存在しなければ)モデルが生成され、Deviseモジュールとして設定されます。generatorは、config/routes.rb
ファイルもDeviseコントローラを指すように修正します。
次に、メール確認やアカウントロックなどのモデルに追加したいオプション設定をチェックしてください。オプションを追加した場合は、(ORMがサポートしていればgeneratorによって作成される)migrationファイルも確認し、適切なセクションのコメントを外してください。例えば、メール確認のオプションを追加した場合、Confirmableセクションのコメントを外す必要があります。そのあとrake db:migrate
を実行してください。
次は、各環境のDevise用メールサーバの設定をします。以下は、config/environments/development.rb
用の設定例です。
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
Deviseの設定を変更したら、アプリケーションを再起動してください。再起動しないと、ログインできなかったりルーティング設定が壊れているというエラーが発生する可能性があります。
Controller filters and helpers
Deviseは、controllerやviewで利用可能なhelperを生成します。ユーザ認証をcontrollerに設定するには、before_actionを追加するだけです(以下は、Deviseのmodelが'User'の例です)。
before_action :authenticate_user!
DeviseのmodelがUserではない場合、"_user"の部分を"_yourmodel"に変更してください。これから紹介する内容が利用できるようになります。
ユーザがサインイン済みかをチェックするには、次のhelperを利用します。
user_signed_in?
現在サインイン中のユーザについては、このhelperが利用可能です。
current_user
セッションにもアクセスできます。
user_session
サインイン、アカウントの確認、パスワードの変更などを行った後、Deviceは画面をリダイレクトするためrootパスを探します。例えば、:user
リソースを利用しているのであれば、user_root_path
が存在しているなら、それが使われます。そうでなければ、デフォルトのroot_path
が使われます。つまり、ルーティングにrootを設定する必要があるということです。
root to: "home#index"
さらに、after_sign_in_path_for
やafter_sign_out_path_for
をオーバーライドしてリダイレクトフックをカスタマイズできます。
DeviseのmodelがUser
ではなくMember
の場合、以下のようなhelperが利用可能です。
before_action :authenticate_member!
member_signed_in?
current_member
member_session
Configuring Models
model内のDeviseメソッドで、該当のモジュールの設定を行うことが可能です。例えば、以下のように暗号化アルゴリズムの選択が可能です。
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :stretches: 20
:stretches
では、 :pepper
、 :encryptor
、 :confirm_within
、 :remember_for
、 :timeout_in
、 :unlock_in
のオプションを定義できます。さらに詳しい情報は、上で説明した"devise:install"のgeneratorが呼び出されたときに生成されたinitializerファイルを確認してください。このファイルは通常、/config/initializers/devise.rb
にあります。
Strong Parameters
独自ビューをカスタマイズする際に、フォームに新しい属性を追加する必要があります。Rails 4では、パラメータのサニタイズをmodelからcontrollerへ移しました。これにより、Deviseはcontrollerでもこの問題を扱えるようになりました。
サニタイズが必要な場合、Deviseでは3つのアクションによりmodelへ各パラメータを渡すことができます。デフォルトでは以下の名前とパラメータになります。
-
sign_in
(Devise::SessionsController#create
) - 認証キー(例えばemail
)のみを許可します -
sign_up
(Devise::RegistrationsController#create
) - 認証キーに加え、password
とpassword_confirmation
を許可します -
account_update
(Devise::RegistrationsController#update
) - 認証キーに加え、password
とpassword_confirmation
、current_password
を許可します
もしその他のパラメータを追加した場合は(the lazy way)、ただbeforeフィルタをApplicationController
を追加します。
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
上記のコードは、パラメータが単純なスカラータイプである場合どんな追加パラメータでも動作します。ネストされた属性の場合(accepts_nested_attributes_for
を利用している場合)、ネストされていることとそのタイプをDeviseに伝える必要があります。デフォルト設定を全部変更したり、カスタマイズした振る舞いをさせることもできます。
ユーザ名とemailを許可する場合は以下のようにします。
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }p
end
もし、登録の際にユーザにロールを割り当てるためのチェックボックスがある場合は、ブラウザはチェックボックスを配列で渡します。配列は、Strong Parameterで許可されていないため、以下のようにDeviseを設定する必要があります。
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation) }
end
許可値リストや、ネストしたハッシュや配列からキーをどのように宣言するかについては以下を確認してください。
Deviseのモデルが複数ある場合は、モデルごとに異なるパラメタに対するサニタイザを設定したくなると思います。この場合は、Devise::ParameterSanitizer
を継承した上で、ロジックを追加することを進めます。
class User::ParameterSanitizer < Devise::ParameterSanitizer
def sign_in
default_params.permit(:username, :email)
end
end
その上で、コントローラの中で利用してください。
class ApplicationController < ActionController::Base
protected
def devise_parameter_sanitizer
if resource_class == User
User::ParameterSanitizer.new(User, :user, params)
else
super # Use the default one
end
end
end
上記の例では、userの:username
と:email
の両方に適用されるようpermitted parametersをオーバライドしています。まじめにやろうとすると、カスタムコントローラで、beforeフィルタを定義することによりパラメータを設定することになります。以降のセクションで、コントローラを設定し、カスタマイズする方法の詳細を説明します。
Configuring views
ここまでは、認証を利用するアプリケーションを簡単に開発するためDeviseを利用しました。しかし、カスタマイズする必要がある場合もある。
Deviseはエンジンであるため、gemの中にビューが全てパッケージされている。これらのビューは始めたばかりの時には役立ちますが、作業をしているうちに変更したくなります。こうした場合は、次のようにgeneratorを呼び出して、アプリケーションにすべてのビューをコピーしてください。
rails genrate devise:views
アプリケーション内に複数のモデル(User
とAdmin
など)がある場合は、Deviseがすべてのモデルで同じビューを利用することを念頭においてください。幸運なことに、Deviseではビューを簡単にカスタマイズすることができます。config/initializers/devise.rb
ファイルにconfig.scoped_views = true
をセットするだけです。
そうしたら、users/sessions/new
やadmins/sessions/new
のようにロールごとにビューを持つことができます。ビューが適切な場所に存在しない場合は、Deviseは、devise/sessions/new
というデフォルトビューを利用します。モデルごとのビューを作りたい場合は、以下のようにします。
rails generate devise:views users
「registerable
とconfrimable
モジュールだけ」というような、ビューのうちいくつかだけを生成したい場合は、-v
フラグでモジュールのリストをgeneratorに渡します。
rails generate devise:views -v registrations confirmations
Configuring controllers
ビューのカスタマイズだけでは足りない場合、以下のステップで、ビューをカスタマイズすることができます。
-
スコープをgeneratorに渡して、コントローラを作成します
rails generate devise:controllers [scope]
スコープとして
users
を使いたい場合、コントローラはapp/controllers/user/
に作成されます。セッションコントローラは以下のような感じです。class Users::SessionsController < Devise::SessionsController # GET /resource/sign_in # def new # super # end ... end
-
コントローラを利用するためのルーティング設定をします
devise_for :users, controllers: { sessions: "users/sessions" }
-
devise/sessions/
からusers/sessions
にビューをコピーします。コントローラがへ高されたので、devise/sessions
にあるデフォルトビューは使われません。 -
最後に、コントローラ上でアクションを変更もしくは拡張します。
コントローラのアクションを完全にオーバライドすることもできます。class Users::SessionsController < Devise::SessionsController def create # custom sign-in code end end
もしくは単に新しい振る舞いを追加することもできます。
class Users::SessionsController < Devise::SessionsController def create super do |resource| BackgroundWorker.trigger(resource) end end end
上記のコードはバックグラウンドジョブのトリガーや、特定のアクション中のロギングイベントに有効です。
Deviseは、サインインの成功や失敗を伝えるのにflashメッセージを利用します。Deviseでは、アプリケーション内でflash[:notice]
やflash[:alert]
を適切に利用してください。flashハッシュのすべてを表示するのではなく、特定のキーを表示してください。特定の環境においては、Deviseは:timeout
キーをflashハッシュとして追加しますが、表示にはテキしていません。もしハッシュをそのまま表示するつもりなら、このキーは削除してください。
Configuring routes
Deviseは、デフォルトでルーティングを設定します。カスタマイズする必要があれば、devise_forメソッドを使ってカスタマイズしてもよいでしょう。以下のようにi18n対応のパスを許可するものを含め、:class_nameや:path_prefixなどのオプションがあります。
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_for
のデモを確認してください。
例えば"/users/sign_in"に加え"/sign_in"を許可したいなど、さらなるカスタマイズが必要な場合は、通常通りルーティングの設定を行い、devise_scope
ブロックで囲うだけでOKです。
devise_scope :user do
get "sign_in", to: "devise/sessions#new"
end
このように設定すると、"/sign_in"にアクセスがあると、Deviseは:user
スコープを利用します。devise_scope
はルーティング設定内ではas
としてもエイリアスされています。
I18n
Deviseは、:noticeや:alertというフラッシュキーで接続された、I18nのflashメッセージを利用します。アプリケーションをカスタマイズするためには、localeファイルを設定してください。
en:
devise:
sessions:
signed_in: 'Signed in successfully.'
ルーティング設定内で特定可能な名前を利用することで、リソースごとに異なるメッセージを作成することもできます。
en:
devise:
sessions:
user:
signed_in: 'Welcome user, you are signed in.'
admin:
signed_in: 'Hello admin!'
Deviseのメーラは、件名を同様にして独立して定義されたものを利用します。
en:
devise:
mailer:
confirmation_instructions:
subject: 'Hello everybody!'
user_subject: 'Hello User! Please confirm your email'
reset_password_instructions:
subject: 'Reset instructions'
利用可能なメッセージについては、以下のlocaleファイルをご覧ください。wikiにある翻訳も利用可能です。
注意: Devise Controllersは、ApplicationControllerを継承しています。アプリ内で複数のlocaleを利用する場合は、ApplicationControllerでI18n.localeを設定しなくてはなりません。
Test helpers
Deviseはspec用にtest helperを含んでいます。利用するには、test/test_helper.rb
ファイルの最後に以下のコードを追加します。
class ActionController::TestCase
include Devise::TestHelpers
end
RSpecを利用しているのであれば、spec/support/devise.rb
かspec/spec_helper.rb
(もしくは、rspec-railsを利用しているのであればspec/rails_helper.rb
)というファイルに以下のコードを埋めてください。
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
end
require 'rspec/rails'
ディレクティブの後で有効であることに気をつけてください。
これで、sign_in
やsign_out
メソッドが利用できる準備が整いました。これらのメソッドはコントローラ内で利用可能です。
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)
覚えておくべきことがふたつあります。
- これらのhelperは、CapybaraやWebratによる結合試験では利用できません。機能試験のみで利用できます。フォームへ入力するかセッションにユーザをセットしてください。
- Deviseの内部コントローラやDevise自体を継承したコントローラを試験する場合は、リクエストの前にどのマッピングが使われるかをDeviseに知らせる必要があります。これはDeviseがルータからこの情報を得るためですが、機能テストはルータを通さないので明確にする必要があります。例えば、userスコープをテストする場合は、シンプルに以下のように記載します。
@request.env["devise.mapping"] = Devise.mappings[:user]
get :new
RSpecでのRails3、Rails4のコントローラの試験については、以下のwikiで詳細を確認してください。
OmniAuth
Deviseは、すぐに様々な認証を利用できるOmniAuthをサポートしています。利用するには、OmniAuthの設定をconfig/initializers/devise.rb
に記載します。
config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
wikiにさらに詳細な情報があります。
Configuring multiple models
Deviseは好きなだけモデルをセットアップできます。上記のUserモデルに加え、認証にタイムアウト機能を備えただけのAdminモデルを作りたい場合は、以下のようにします。
# Create a migration with the required fields
create_table :admins do |t|
t.string :email
t.string :encrypted_password
t.timestamps null: false
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を呼ぶ出すだけでも可能です。
これらのモデルは完全に異なるルーティングになることを注意してください。サインイン、サインアウトなどについて、コントローラを共有することは ありませんし 、 できません 。同じアクションを異なるロールで共有したい場合は、ロールのカラムを使うか、それに特化したgemを利用するというようなロールベースのアプローチをお勧めします。
ActiveJob Integration
バックエンドでのキューイング用にActionMailerのメッセージ配信をするために、Rail4.2とActiveJobを利用している場合は、モデル内でsend_devise_notification
メソッドをオーバーライドすることにより既存のキューを通してDeviseのメールを送信することができます。
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
Password reset tokens and Rails logs
Recoverableモジュールを有効にする場合は、パスワードリセットのトークンが盗まれると、攻撃者がアプリケーションにアクセスできてしまうことに注意してください。Deviseは、ランダムでセキュアなトークンを生成し、データベースにトークンのdigestのみを保存します。これは平文ではありません。しかしながら、Railsにおけるデフォルトのロギングでは、ログファイルに平文のtokenを漏らしてしまいます。
- Action MailerはDEBUGレベルにて、送付メールのすべてのコンテンツをログに出力します。ユーザに送付されたパスワードリセットのトークンが漏れることになります。
- Active JobはINFOレベルにて、各キューに対する全ての引数をログに出力します。パスワードリセットのメールを送付するために
deliver_later
をDeviseで設定した場合、パスワードリセットのトークンが漏れることになります。
RailsはデフォルトでproductionのログレベルをDEBUGに設定します。ログにトークンが出力されないようにしたいのであれば、productionのログレベルをWARNに変更してください。config/environments/production.rb
内で以下のように設定します。
config.log_level = :warn
Other ORMs
Deviseは、ActiveRecord(デフォルト)とMongoidをサポートしています。他のORMを利用するためには、initializerファイルでrequireしてください。
Additional information
Heroku
Ruby on Rails 3.2のHeroku上でDeviseを使うには、以下のように設定します。
config.assets.initialize_on_precompile = false
その他の潜在的な問題については、http://guides.rubyonrails.org/asset_pipeline.html で紹介されています。
Warden
DeviseはWardenをベースにしています。Wardenは、Daniel Neighmanによって構築されたRackベースの認証フレームワークです。Wardenについては以下が参考になります。
Contributors
DeviseにはたくさんのContributorがいます。以下に全員記載してます。
Lisence
MIT License. Copyright 2009-2015 Plataformatec. http://plataformatec.com.br
You are not granted rights or licenses to the trademarks of Plataformatec, including without limitation the Devise name or logo.