はじめに
Ruby on Rails におけるセッションについて理解を深める機会があったので、せっかくなので Rails 入門者向けにまとめてみました。
注意事項
- 初心者向けですが、HTTP や Cookie の基礎知識が必要です
- Rails のバージョンによって細かい仕様が異なる可能性があります
- この記事を書いた時は Rails v8.1.0 を参照しました
- セッションストアをデフォルトの CookieStore に設定している場合を想定しています
セッションとは
セッションの概念と仕組みを丁寧にまとめられている素敵な記事を見つけたので、それを紹介します。
手短に説明すると、Webにおけるセッションは「ステートレスな HTTP でステートフルな操作を可能にするための仕組み」で、Cookieを使用して実現することが多いです。
「ステートフル」というのは、具体的には「ログインしている状態」や「ECサイトのカートの状態」などが維持されるといった例が挙げられます。
Railsガイドによると、以下のように説明されています。
アプリケーションはセッションを用いて、多くのユーザーがアプリケーションとやりとりできるようにしつつ、各ユーザー固有のステートを維持します。たとえばセッションを用いることで、ユーザーが認証されれば以後のリクエストでサインインしたままにできます。
Rails セキュリティガイド - Railsガイド
Rails におけるセッション
セッションは Rails の機能の一つとして用意されていて、Controller でアクセスできる session というオブジェクトが存在します。(実体は ActionDispatch::Request::Session というクラスのインスタンスです)
session はユーザーを識別するためのセッションIDなどを含む、Hash のように扱うことができるオブジェクトです。session[:hoge] = 123 のようにデータ(セッションデータ)をセットしたり、session[:hoge] で取り出したりできます。
このセッションIDやセッションデータをどうやって維持しているかというと、デフォルトでは Cookie としてリクエストやレスポンスに含めることで維持しています。
補足
セッションデータの保存場所はセッションストアと呼ばれ、config/initializers/session_store.rb で設定されています。デフォルトのセッションストアは CookieStore (全部 Cookie に保存される)になっていて、 この設定を変えると Cookie 以外の場所(Redis など)にセッションデータを保存できます。
Rails が Cookie でどのように使ってセッションデータを維持しているか、次の節で紹介します。
Rails が Cookie でセッションデータを維持する仕組み
どんな流れでセッションデータを維持するのか、以下の図を使って説明します。
説明のために簡略化している部分があります。また、セッションが保存されるCookieのキーは _session としています。
(このキーも config/initializers/session_store.rb で設定できます。)
- ① 最初にブラウザから送られたリクエストにはセッションがありません
- ② Rails はセッションが無い場合、新しくセッションを作成します
- 例として、ここで
session[:hoge] = 123というデータを保存したとします
- 例として、ここで
- ③
Set-Cookieヘッダーに暗号化 & 署名したセッションデータをセットして、レスポンスを返します - ④ ブラウザは
Set-Cookieヘッダーを読み取り、Cookie を保存します - ⑤ ブラウザからのリクエストに Cookie が含まれます
- ⑥ Rails は Cookie を読み取り、復号することでセッションデータを参照できます
-
session[:hoge]にアクセスすると123が取得できます
-
このように Cookie を使うことで、 session に入れた値をリクエスト間で共有することができます。例えばログイン時に Rails session[:user_id] = user.id のようにセットすれば、どのユーザーからのリクエストか Rails が識別することができます。
session の活用事例: flash
Rails には flash という機能があり、flash[:notice] = "ログアウトしました" のように flash を設定した後 redirect_to でリダイレクトすると、リダイレクト先のページで「ログアウトしました」を表示することができます。実は flash の内部で session が使用されているため、リダイレクト先のURLへのリクエストに含まれるセッションの Cookie から flash の内容を取り出して表示しています。
Rails のセッションのセキュリティ
セッションの仕組みの基礎は説明した通りですが、セッションを扱う上で重要なのがセキュリティです。
例えば、あるユーザーのセッションの Cookie が悪意のあるユーザーに奪われてしまうと、悪意のあるユーザーのリクエストが、Railsでは元のユーザーのリクエストとして識別されてしまうため、情報漏洩や、意図しない操作が行われてしまう可能性があります。(このような攻撃はセッションハイジャックと呼ばれます)
対策として、Cookie が奪われないようにする方法はいくつかありますが、ここでは詳細は省きます。Rails セキュリティガイドなどを参考にしてみてください。
参考