はじめに
Railsの認証システムであるDeviseは、非常に強力で柔軟性がありますが、複数のユーザーモデルを管理する際には注意が必要です。特に、異なるユーザーモデル間での同時ログインを避けたい場合、デフォルトの設定では対応できないことがあります。この記事では、Deviseを使用して、複数のモデルで同時ログインが発生しないようにする方法を説明します。
課題の説明
Deviseを使って複数のモデル(例えば、Company、Staff、AdminUser)を認証管理している場合、一つのブラウザセッションで複数のモデルに同時にログインされると予期せぬ問題やセキュリティリスクが生じる可能性があります。特に、管理者としてログインしている状態で他のユーザーを作成し、そのユーザーが自動的にログインされる場合、問題が複雑化します。
解決策の実装
Deviseの設定変更
まず、Deviseの設定を変更して、複数のログインを一度に管理しないようにします。
# config/initializers/devise.rb
Devise.setup do |config|
config.allow_unauthenticated_access_to = [:new, :create]
config.sign_out_all_scopes = true
end
この設定により、新たにログインするユーザーモデルが既存のログインセッションを上書きし、同時に複数のモデルにログインすることを防げます。
モデルごとのログイン管理
特定のモデルで新たなユーザーを作成する際に、自動的なログインをスキップすることも重要です。以下のようにStaffsController
のcreate
アクションをカスタマイズします。
# app/controllers/staffs_controller.rb
@staff = Staff.new(staff_params)
authorize! :create, @staff # CanCanCanを使って手動で認可チェック
super do |staff|
if staff.persisted?
# CompanyまたはAdminUserが既にログインしている場合は、Staffの自動ログインをスキップする
unless company_signed_in? || admin_user_signed_in?
sign_in(staff) unless staff_signed_in?
end
staff.assign_attributes(staff_params)
if staff.persisted?
unless company_signed_in?
sign_in(staff) # Companyがログインしていない場合のみStaffをログインさせる
end
else
render :index
end
end
end
end
このコントローラーのカスタマイズにより、既にログインしているユーザー(CompanyやAdminUser)がいる場合、新たに作成されたStaffは自動的にログインされません。
まとめ
Deviseを使用する際に複数のモデル間での同時ログインを管理することは、セキュリティの観点から非常に重要です。上記の設定とコード例を参考に、アプリケーションのセキュリティを強化し、意図しないログインを防ぐことができます。