DBベースのDeviseを利用したログイン処理や、管理者によるユーザー成りすましログイン時に、認証情報やセッション情報がどのように保持・管理されているのかを改めて整理してみました。
本検証で利用した主なGem
devise– ユーザー認証機能activerecord-session_store– DBベースのセッション管理
各種設定
セッション関連の設定概要
- セッションストア:
active_record_store(DBベース) - シリアライザー:
:json - セッションキー:
_devise_project_session - 設定ファイル:
config/initializers/session_store.rb– セッションストアの設定Rails.application.config.session_store :active_record_store, key: '_devise_project_session'config/application.rb– シリアライザーの設定# Configure session serializer ActiveRecord::SessionStore::Session.serializer = :json
:jsonシリアライザー
- 内部的にはRubyのJSONモジュール(
parse/generate)を使用 - DB保存値は、データーベースの種類や参照方法に依存し、Base64エンコードされているケースと生データがそのまま入っているケースに分かれる。
- SQLite3の場合、sessions.dataにBase64エンコードを実行した値が入っていた
- Rails console経由では自動的にデシリアライズされて人間が読める形のHashとして参照可能
- PostgreSQLの場合、sessions.dataにBase64エンコードされてない値が入っていた
- sessions.data はSQLのWHERE句で検索可能
- DB登録値を人間が直接みても把握しやすい
- SQLite3の場合、sessions.dataにBase64エンコードを実行した値が入っていた
- SQLite3等のBase64エンコードされた値が登録されている場合でも、Rails console経由では自動的にデシリアライズされて人間が読める形のHashとして参照できる
成りすましログイン実装
実装方法
今回は devise_masquerade Gem は使用せず、独自に成りすましログインを実装しています。
コントローラー
管理者用の成りすまし処理は、専用コントローラーapp/controllers/admins/masquerade_controller.rb
にて実装
createアクション: ユーザーとしてなりすましログインsession[:admin_id]に管理者IDを保存sign_in(user, scope: :user)でユーザーとしてログイン- 管理者とユーザーの両方のセッションを同時に保持
backアクション: 管理者に戻るsession[:admin_id]を削除sign_out(:user)でユーザーからログアウト- 管理者は最初からログインしたままなので、再ログイン不要
動作の仕組み
- 管理者がユーザーとして成りすましログインすると、
session[:admin_id]に管理者IDを保存 - Deviseの
sign_inメソッドでscope: :userを指定してユーザーとしてログイン - 管理者とユーザーのセッションが同時に保持される(Wardenの機能)
- 管理者に戻る際は、
session[:admin_id]を削除し、ユーザーからログアウト - 管理者のセッションは保持されているため、自動的に管理者としてログインした状態に戻る
挙動の確認
通常ログイン時の挙動
ユーザーとしてログインした際に、ブラウザ(Cookie)およびDB(sessionsテーブル)に保持される情報を確認します。
1. ログアウト状態でトップページにアクセスしてユーザーログイン画面に移動
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 3d61eb186f276193f9b39960c19a1f24 | セッション |
2. ユーザーとしてログイン
2-1. Remember me機能を利用しない場合
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 31583c53362942cf35d9c80f132b8d87 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.session_id | 2::f6f080e4d69a6fd4656417df1025c18985119ff342156ed7b4e55a4af278e100 |
| sessions.data | {“value”:{“warden.user.user.key”:[[1],”$2a$12$GYNzAz1II/RDbA6.nvq0ae”],”flash”:{“discard”:[],”flashes”:{“notice”:”Signed in successfully.”}},”_csrf_token”:”rmYAA8tPTiPgC3f68k71-1SEY0SaUq62lMVrrDp_nOg”}} |
| users.id | 1 |
| users.email | user1@example.com |
| users.remember_created_at | NULL |
2-2. Remember me機能を利用した場合
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 68d2c1c36f3fd0573c0dce3fa3c29744 | セッション |
| remember_user_token | eyJfcmFpbHMiOnsibWVzc2FnZSI6Ilcxc3hYU3dpSkRKaEpERXlKRWRaVG5wQmVqRkpTUz.. | 2026-01-21T04:16:07.000Z |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.session_id | 2::c3a5e169d537d3ac871b58b11f2f97fc99f24bdc517fc70f508c290726770ed0 |
| sessions.data | {“value”:{“flash”:{“discard”:[],”flashes”:{“notice”:”Signed in successfully.”}},”warden.user.user.key”:[[1],”$2a$12$GYNzAz1II/RDbA6.nvq0ae”],”_csrf_token”:”ngh6n6CBifCfjW6JiTkr3bQvAcvjcGoVYooASYLIg9o”}} |
| users.id | 1 |
| users.email | user1@example.com |
| users.remember_created_at | 2026-01-07 04:16:07.910839 |
3. ログアウト実行
3-1. Remember me機能を利用しない場合
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 0462a342200dab2686e39dc0f248147f | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.session_id | 2::edf7dbbadc9365f656643aafa2290de12db4c3a3ef5141d54088cc9691266820 |
| sessions.data | {“value”:{“flash”:{“discard”:[],”flashes”:{“notice”:”Signed out successfully.”}},”_csrf_token”:”XDJ4lP_s9S_pBf2bOy_n_JZ4ab9ft0wFSiNTnEFnTNg”}} |
| users.id | 1 |
| users.email | user1@example.com |
| users.remember_created_at | NULL |
3-2. Remember me機能を利用した場合
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | d8550d86bf7d7666c53648950ecb9b6e | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.session_id | 2::ebc42a5957b7b2b0e16f54c036fe4a0c2f620f180b1d2f2a8f19d5290e081931 |
| sessions.data | {“value”:{“flash”:{“discard”:[],”flashes”:{“notice”:”Signed out successfully.”}},”_csrf_token”:”xkJTq4PsnulwO5YEkcDh2D_5FDqhTpcMsSpuPOtwmgo”}} |
| users.id | 1 |
| users.email | user1@example.com |
| users.remember_created_at | NULL |
代行ログイン時の挙動
管理者がユーザーとして成りすましログインを行った際の、ブラウザ側の保持情報とDB側の情報を確認します。
なおこちらは、ログイン前もDB情報を確認しています。
1. ログアウト状態でトップページにアクセスして管理者ログイン画面に移動
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 30208199886f94c6d1b49c75c88436e2 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.id | 21 |
| sessions.session_id | 2::ff0ada7f16c44bbaf03becb1d89075db289f32666b0a3ca60ffc3c69a63f7bab |
| sessions.data | {“value”:{“_csrf_token”:”kAUCHbWQkptRXCjjbuSKQI2vgHyvp0v6aPj5o5FpGos”}} |
| admins.id | 1 |
| admins.email | admin@example.com |
| admins.remember_created_at | NULL |
2. 管理者としてログイン
※ Remember me機能を利用しない場合のみ実施
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | e509485017fe1845c44ae0f5df3658f9 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.id | 22 |
| sessions.session_id | 2::eaa15dfd031aa539eaa570de66f94e686f63aa41f4aa34c6b5b2e680cea6cce4 |
| sessions.data | {“value”:{“warden.user.admin.key”:[[1],”$2a$12$7WI0p3xhsuv.PGH9eAkcoe”],”flash”:{“discard”:[],”flashes”:{“notice”:”Signed in successfully.”}},”_csrf_token”:”hl0BRIuhyRFgSwRpJyi_jYzvuCBptcV18vhfbfFEz4M”}} |
| admins.id | 1 |
| admins.email | admin@example.com |
3. ユーザーで成りすましログイン
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 0fed9dd74cb380d4b6c2ca4cc0a45d32 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.id | 23 |
| sessions.session_id | 2::e569625366bf233c0b88f0ec4b96fc2203b9235121a2178eb78fa4faa70980f8 |
| sessions.data | {“value”:{“warden.user.admin.key”:[[1],”$2a$12$7WI0p3xhsuv.PGH9eAkcoe”],”flash”:{“discard”:[],”flashes”:{“notice”:”user2@example.comとしてログインしました”}},”_csrf_token”:”hl0BRIuhyRFgSwRpJyi_jYzvuCBptcV18vhfbfFEz4M”,”admin_id”:1,”warden.user.user.key”:[[2],”$2a$12$CRQBRFPsBNpJkcxBfPaMYu”]}} |
4. 成りすましユーザーからログアウトして管理者に戻る
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 0fed9dd74cb380d4b6c2ca4cc0a45d32 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.id | 23 |
| sessions.session_id | 2::e569625366bf233c0b88f0ec4b96fc2203b9235121a2178eb78fa4faa70980f8 |
| sessions.data | {“value”:{“warden.user.admin.key”:[[1],”$2a$12$7WI0p3xhsuv.PGH9eAkcoe”],”flash”:{“discard”:[],”flashes”:{“notice”:”管理者に戻りました”}},”_csrf_token”:”hl0BRIuhyRFgSwRpJyi_jYzvuCBptcV18vhfbfFEz4M”}} |
| users.id | 1 |
| users.email | user1@example.com |
| users.remember_created_at | NULL |
5. 管理者からもログアウトする
cookie情報:
| 名前 | 値 | 期限 |
|---|---|---|
| _devise_project_session | 2d97e48df0b859c7f296939c078a0142 | セッション |
DB情報:
| テーブル名.カラム名 | 値 |
|---|---|
| sessions.id | 24 |
| sessions.session_id | 2::7d291b3f59bb886879269b3708a59a1b8324a04cab308985984cbd594f7f8fc7 |
| sessions.data | {“value”:{“flash”:{“discard”:[],”flashes”:{“notice”:”Signed out successfully.”}},”_csrf_token”:”ULFBdwfVWuNtVZpsblE88FcZelC_c1LThqtTJ_jyI2E”}} |
検証結果
ログイン・ログアウト・成りすましといった操作のたびに、sessions.id, sessions.session_idや、ブラウザのセッション情報が変化することで、不正ログインを防ぐ仕組みになっていることが確認できました。
ユーザーサイドから考えると、普段からきちんとログアウトしておくのが重要であると再認識しました。
運用時のTips
成りすましログイン後にログアウトを行わず、別のユーザーへ続けて成りすましログインした場合の挙動
先に成りすました状態を維持したまま、後続のユーザー情報でセッション内容が更新される挙動が確認できました。
セッションデータ内のユーザー識別情報(warden.user.user.key)が、後続の成りすましログインによって上書きされています。
{
"value": {
"flash": {
"discard": [],
"flashes": {
"notice": "user2@example.comとしてログインしました"
}
},
"warden.user.admin.key": [[1], "$2a$12$7WI0p3xhsuv.PGH9eAkcoe"],
"_csrf_token": "Ec7oxb5a3ss3VbRTRy-WfV1SO3VanJau-WEmcG-PJME",
"admin_id": 1,
"warden.user.user.key": [[2], "$2a$12$CRQBRFPsBNpJkcxBfPaMYu"]
}
}sessions テーブルが肥大化した場合の対処
ActiveRecord Session Store の公式ドキュメントでも言及されていますが、期限切れのセッションや不要なセッションデータが蓄積し続けるのを防ぐため、本番環境ではセッション削除用のタスクを定期的に実行することが推奨されています。
デフォルト設定では、一定期間(例:30日)更新されていないセッションが削除対象となり、この期間は環境変数によって調整可能です。
ActiveRecord Session Store 公式ドキュメント(2026年1月閲覧):
https://github.com/rails/activerecord-session_store/blob/master/README.md#installation
