はじめに
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ヘッダーに含めて、リクエストすることによってステートフルを実現