【Rails】セッションとその保存場所について

# はじめに
こんにちは。アメリカで独学でエンジニアを目指している者です。
以前の記事ではセッションについて取り上げましたが、Railsに関する記事はまだ執筆していなかったため、今回はRailsにおけるセッションの役割や保存場所について解説します。

## セッションとは？

Webアプリケーションでは、HTTPのリクエストとレスポンスは本来「ステートレス」（状態を持たない）通信であるため、ユーザーごとの状態を持続的に管理する仕組みとして セッション が利用されます。
セッションとは、ユーザーがWebアプリケーションにアクセスしてから離脱するまでの間、アプリケーション側がユーザーを特定して状態を保持する仕組みです。
Railsでは、このセッションに関わるデータを簡単に管理できるよう、コントローラー内で `session` というハッシュ形式のオブジェクト（例：`session[:キー]`）を提供しています。



## Railsにおけるセッションの役割

### ユーザーのログイン状態管理

たとえば、`session[:user_id]`のようにユーザーのIDをセッションに保存することで、リクエストが増えても同じユーザーとして扱うことができます。ログインが成功すると、

```ruby
session[:user_id] = user.id
```

各アクションで `session[:user_id]` を確認することで、ユーザーがログインしているかどうかを判定できます。

### 一時的なデータの保持

Railsチュートリアルでは扱っていませんが、ショッピングカートの情報や複数ページにまたがるフォームの入力内容など、一時的な情報をページ間で保持する際にもセッションが利用されます。
ただし、セッションはあくまで一時的なストレージであるため、大容量のデータを保存するのは推奨されません。

---

## セッションの保存場所

Railsでは、セッションの「保存場所（ストア）」を切り替えることができます。
デフォルト設定は**CookieStore**ですが、他にも**ActiveRecord::SessionStore**や**Redis**など、サーバーサイドで管理する方法も存在します。

### CookieStore（デフォルト）

- **仕組み**
  Railsのデフォルトは`CookieStore`で、セッションデータは暗号化・署名された**Cookie**としてブラウザに保存されます。サーバー側にセッションデータを保管しないのが特徴です。

  Railsチュートリアルでもこの仕組みを採用しているはずです(8章まで)

- **CookieStoreのメリット**

  - セッション情報をサーバーが保持しないため、スケーリングが容易。
  - レスポンスごとにサーバー側のストレージを介さないため、速度が速い。

- **CookieStoreのデメリット**

  - Cookieに保存できるデータ量に制限がある（通常4KB程度までが推奨）。
  - データは署名・暗号化されているため改ざんは検出できるが、サイズが大きくなると通信量が増加。

### サーバーサイドストア

Railsでは、CookieStore以外にもいくつか代表的なサーバーサイドストアがあります。

#### ActiveRecord::SessionStore

- **仕組み**\
  **セッション情報をデータベース（テーブル）に保存**し、CookieにはセッションIDのみを保存します。\
  データベースを使うため、セッションデータの読み書きにはクエリが走ります。

- **メリット**

  - 大量のセッションデータを扱える。
  - データベースを介しているので、Cookieの容量制限がなくなる。
  - サーバー側でセッションを管理するため、セキュリティ面の制御がしやすい。

- **デメリット**

  - リクエストごとにDBへのアクセスが発生するため、負荷が増える可能性がある。
  - データベースのマイグレーションが必要。

#### RedisやMemcachedなど

- **仕組み**
  セッションを**インメモリデータストア（Redis、Memcachedなど）に保存**し、CookieにはセッションIDのみを保存します。
- **メリット**
  - 低レイテンシで大量のセッションを扱える。
  - 分散環境でも比較的スケールしやすい。
- **デメリット**
  - インメモリである分、データが揮発しうる（Redisでも永続化は可能だが設定が必要）。
  - 追加のミドルウェアが必要。

---

## Railsがセッションを生成するタイミング

意外に思われるかもしれませんが、Railsでは**ログイン前でもセッションは存在**します。
ユーザーがアプリケーションにアクセスした時点で、Railsはそのユーザー専用のセッションを作成し、CookieStoreであれば暗号化した空のCookieをブラウザに送信します。
ログイン時に`session[:user_id]`を設定することで、セッションを活用してログイン状態を管理するのが一般的です。

---

## セッションのリセットや有効期限

### `reset_session`メソッド

ログアウト時などに呼び出すことで、セッションを初期化し、新しいセッションIDを発行します。
これにより、**セッションフィクセーション攻撃**を防ぎ、安全な新規セッションに切り替えることができます。

```ruby
def log_out
  reset_session
  redirect_to root_url
end
```

### Cookieの有効期限

これについてはまだ扱っていませんが、CookieStoreの場合は、`config/initializers/session_store.rb`で`expire_after`オプションを指定することで、Cookieの有効期限を設定できるようです

```ruby
Rails.application.config.session_store :cookie_store, key: '_app_session', expire_after: 30.minutes
```

これを設定しない場合は**ブラウザのセッションCookie**として扱われ、ブラウザを閉じると削除されるのが一般的です。

---

## まとめ

- **Railsのセッション**は、`session[:キー]`というハッシュ形式で、ユーザーごとの一時的な情報（ログインIDなど）を簡単に保持するための仕組み。
- **CookieStore**（デフォルト）では、暗号化・署名されたCookieにセッションデータが保存され、サーバー側にデータを持たないのが特徴。
- サーバーサイドストア（ActiveRecord、Redisなど）を利用する場合は、CookieにはセッションIDのみが入り、実際のデータはサーバーで管理する。
- ユーザーがアプリケーションにアクセスした時点で、**匿名セッション**が生成される。ログイン時に`session[:user_id]`を登録することで、ログイン状態をセッションで管理する。
- `reset_session`は、セッションを新しく生成し直すため、ログアウト処理やセキュリティ対策で重要な役割を担う。