はじめに
Railsではdevise
という、それはそれは便利な認証機能用のgem
がありまして、それに頼り切ってしまっていたためcookie
がどうとかsession
がどうとかという根本的な理解ができていませんでした。
それが最近バレてしまったので、この機会にsession
とcookie
についてまとめたいと思います。
Cookie
cookie
は、ステートレスなHTTPプロトコル
をステートフルにすることができる代物です。
元来、HTTPリクエストはステートレスであるため、前後のリクエストとの関係を持つことはなく独立したものです。
なので、1つ前のリクエストの内容を引き継ぐみたいなことができません。
これを解決するのがcookie
です。
サーバーはリクエストがあると、以後同じ相手からのリクエストを特定するためにset-cookie
ヘッダーを付与してレスポンスを返します。
その後のリクエストでは、そのset-cookie
ヘッダーに指定された値をcookie
ヘッダーに付与してリクエストを送ることでステートフルを実現します。
ブラウザは優秀なので、レスポンスのset-cookieヘッダーで指定された値をリクエストのcookie
ヘッダーに自動で指定してくれますが、curlコマンドなどを使うときはオプションを指定する必要があります。
curl -b "key=value" http://example.com/
Session
session
はユーザーに固有のステートを維持するためのデータ貯蔵庫です。
バックエンド側は、各ユーザーにセッションオブジェクトを割り当てることによって、どのユーザーからのリクエストかを識別できるようにしています。
session[:user_id] = @user.id
sessionはActionDispatch::Request::Session
クラスのインスタンスで、[:user_id]
はインスタンスメソッドです。
sessionが呼ばれるたびに新しいインスタンスが生成されるので、上書きされることはありません。(session[:user_id]
だったら同じkey
に値を代入してるから上書きされるだろ!と思ってました...)
RailsではActionDispatch::Session::CookieStoreをデフォルトのストレージ(貯蔵庫)にしています。※ ここがcookieとsessionが交わる地点
cookie store
では、生成されたsessionをいい感じに暗号化してくれて、それをレスポンスに乗っけてくれます。
また、cookie store
だけでなくデータベースやキャッシュもセッションストレージとして使用することができます。
まとめ
リクエスト
↓
sessionオブジェクトの作成
↓
cookieStoreに保存される
↓
set-cookieヘッダーで指定してレスポンスを返す
↓
set-cookieで指定されたハッシュをcookieヘッダーに含めて、リクエストすることによってステートフルを実現