モチベーション

今更だけど,Webにおけるクッキー,セッション,セッション管理の意味を明確に説明できるようにしたい.

背景

Google先生に”クッキー セッション 違い”と尋ねたことがある人は多いのではないだろうか?多分に漏れず僕もその一人である.検索結果からは沢山,クッキーとセッションについて説明しているサイトが引っかかるのはいいのだが,皆説明が異なる.要するにわかりにくいものなんだと思う.これは,英語で”session cookie difference”と検索しても大量にひっかかるので世界共通のようだ.ということで,今回自分なりにWebにおけるクッキー,セッション,セッション管理を理解し,なぜ混乱しやすいのかをまとめたいと思う.

HTTPはステートレスなプトロコル

HTTPはステートレスなプロトコルであり,状態は持たない.クライアントがリクエストを投げてサーバがレスポンスを返す,このキャッチボールを1往復したところで通信は切れる.つまり,一度目の通信でクライアントから某かの情報を受け取ったとしても,二度目の通信は前の通信の状態はは引き継がない全く関係のない通信になる.これが,HTTPの通信の原則である. 一方,前の通信の状態がわからないと不都合なケースも有る.Amazonでショッピングをするのを例に考えてみよう.Amazonを利用するユーザは商品の検索,選択,購入を行う.これらのアクションはサーバから見るとクライアントからの異なるリクエストである.先ほど説明した通りHTTPはステートレスなプロトコルなので,本来は商品を選択する通信が終了した後,商品の購入のリクエストをサーバに投げても選択した商品の情報は保持しておらず,ユーザが商品を購入できないことになってしまう.しかし,現実は,ご存知の通り,選択した商品はそのまま購入できる.これはWebアプリケーションの開発者が複数のHTTP通信をステートフルな通信に見せかけるような実装をしているからである.

クッキーとセッション

HTTPをステートフルな通信に見せかける方法は大きく分けて2種類あり,1つはクッキーを利用する方法,もう一つはセッションを利用する方法である.(ステートレスだとか,ステートフルだとか良く説明に使われるが,平たく言えば,サーバが通信記録のあるクライアントを判別したいケースがWebアプリケーションではしばしば起こる.それを実現するために有るのがクッキーとセッションだ.)それぞれについて説明していこう.

A cookie, also known as an HTTP cookie, web cookie, Internet cookie, or browser cookie, is a small piece of data sent from a website and stored in a user’s web browser while the user is browsing that website. Every time the user loads the website, the browser sends the cookie back to the server to notify the website of the user’s previous activity.[1] Cookies were designed to be a reliable mechanism for websites to remember stateful information (such as items in a shopping cart) or to record the >user’s browsing activity (including clicking particular buttons, logging in, or recording which pages were visited by the user as far back as months or years ago).

上に書いたのは,WikipediaのHTTP Cookieの説明だ.この説明文は簡潔にまとまっているのでそのまま引用させてもらった.自分の言葉で簡単に説明すると,クッキーの実態はHTTPヘッダーに格納できるテキストファイルであり,クライアントのブラウザに保存されるのが特徴である.Webにおいてサーバがクライアントに直接情報の書き込みをすることは許されていないが,唯一の例外がこのクッキーでサーバとの通信状態を保持するのにクッキーに格納された情報が利用される.クッキーを用いたステートフルな通信の流れは以下のとおりである..

  1. クライアントはサーバAに対するクッキーをもっていない状態でリクエスト1を投げる.
  2. サーバAはリクエスト1にクッキーが含まれていないことを判別し,通信の状態(ユーザのID,パスワード,サイトで行った動作,訪問回数など)を格納したクッキーをレスポンス1に乗せて返す
  3. クライアントのブラウザがこのクッキーを保持する
  4. サーバAにリクエスト2を投げる時にブラウザがクッキーをHTTPのヘッダーに格納して通信をする
  5. サーバAは受け取ったクッキーからクライアントを判別し関連した以前の通信状態と関連させる

20141205_cookie_only

先ほど,クッキーの一番の特徴はクライアント側に保存することと述べた,ユーザのログインを維持したい場合は,ユーザID,パスワード,通信の状態などをクッキーに保存する必要がある.しかし,機密性の高い情報をクッキーに保存すれば,サーバと通信する度にそれらをHTTPヘッダに設定することになる.また,クッキーはクライアント側で改ざん可能であることも推察できるだろう.従って,クッキーだけでステートフルを作るのはセキュリティの観点から望ましくない.そこで,一般的には次のセッションを使った方法でHTTPをステートフルな通信を作り出す.

セッション

セッションはクライアントとサーバの通信の状態を保持する.セッションを利用して複数のHTTP通信を1つのまとまりとして扱うことを”セッション管理”と呼ぶが,クッキーとの違いはセッションはサーバ側に保存されることにある.サーバ側ではセッションID(あるセッションと紐付いたキー)とセッションを保存しておき,セッションIDのみ何らかの手段でクライアントに渡す.セッションIDをクライアントに渡す手段としてはクッキーを利用する方法や,URLのクエリストリングに渡す方法,hidden属性に渡す方法があるが,セキュリティの観点から一般的にはクッキーを使うことが多い.クライアントはセッションIDをクッキー経由でサーバに渡すことで,以前の通信の状態を保持したセッションを取り出すことができる.

20141205_session_cookie

20141205_session_connection

何が混乱の元なのか?

僕が考えるに,クッキーとセッションが混在しやすい理由はセッション管理にクッキーも使われるからだと思う.セッション管理は概念の話でその実現方法は開発者に委ねられている.多くはサーバ側のセッションを引き出すためにクッキーにセッションIDを保存する方法が採られるが,この場合のクッキーは手段で,他の手段を利用しても構わない.僕が最初にセッション管理を勉強した時に混乱したのは,”セッションを使うか,クッキーを使うかじゃないの?”という状態になってしまったからで,クッキーのみを使う方法とセッション管理の手段としてクッキーを使う区別がついていなかったのだ.

なので,クッキーとセッションの違いを説明するときは基本的には,セッションはサーバ側に,クッキーはクライアント側に保存するという理解でOKだと思う.

余談だが,クッキーはきちんと仕様がRFC2965として定義されている.(もともと,NetScape社がセッション管理のために独自仕様のCookieを生み出したが,現在は標準化されたものがHTTPで利用されている.)

まとめ

  • クッキーとセッションはHTTPの通信をステートフルな通信に見せるためにある.
  • クッキーはクライアント側に,セッションはサーバ側にデータを保存する.
  • クッキーのみを使ったステートフルな通信の確立はセキュリティ的に問題があるので利用しない.
  • セッション管理ではクライアント側のクッキーにセッションIDを保存し,それ以外の情報はサーバ側のセッションに保存する
  • クッキーとセッションがわかりにくいのは,セッション管理でセッションIDをクライアントに渡す手段としてクッキーを使うため

参考情報

セッション,クッキーについて