新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

クッキー・セッションの仕組みメモ

Webサイトで、クッキーとセッションを使って、ユーザーがサイトに接続し続ける仕組みを説明した、個人的メモです。

ざっくりとした概念的なメモで、厳密な仕様ではありません。

HTTP通信の問題点

  • HTTP通信は1回1回の単発の通信なので、接続を維持し続けることができない
  • HTTP通信はユーザー識別の仕組みが無いので、どのユーザーからの接続かを判別することができない
  • なので、一連のHTTP通信で、ユーザー接続を維持し続けるには、何かしらの仕組みを実装する必要がある

解決方法

ユーザー認証完了後、サーバー側でユーザー識別子を発行し、ブラウザへのレスポンスで識別子を送り、次回以降ブラウザからサーバーにアクセスする際に、毎回その識別子をサーバーに送ることにより、サーバー側でどのユーザーからのアクセスかがわかるようにする。

そして、その識別子のやり取り方法の1つとして、クッキーを用いる方法がある。

クッキーとは?

ざっくり仕様等箇条書き

  • クッキーとは、変数名とその値のペアのデータのこと
  • クッキーはサーバー側で設定して、ブラウザにレスポンスとして送る
  • 受け取ったクッキーはブラウザに保存される
  • ブラウザが再度そのサイトにアクセスする際、保存されているクッキーをサーバーに送る
  • ブラウザ側でクッキーに変数を追加したり、既存の変数の値を変更することもできる
  • クッキーには有効期限を設定できる
  • クッキーの有効範囲を、ドメインやパスで絞ることができる
  • クッキーの有効範囲を、ドメインやパスで絞った場合、そのクッキーを、他のドメインやパスのサーバーから見ることはできない

一番単純な実装(セキュリティ的にNG)

  • ユーザーがログイン完了した時点で、サーバー側で変数「ユーザーID」、値「ユーザーIDの値」のクッキーを作って返す
  • 以降、ブラウザからサーバーにアクセスする際、そのクッキーがサーバーに送られる
  • サーバー側では、受け取ったクッキーから「ユーザーID」値を取得して、ユーザーを特定することにより、接続を維持する

一番単純な実装の問題点

  • 仕様上、ブラウザ側でクッキーが見れて変更できるので、なりすましができてしまう

一番単純な実装の問題点の解決方法

  • サーバー側ではユーザーIDではなく、暗号化されたユーザー識別子をクッキーとしてブラウザーに送る
  • この暗号化されたユーザー識別子を、一般的に「セッションID」と呼ぶ
  • ブラウザからサーバーにアクセスすると、サーバー側では受け取ったクッキーから「セッションID」を取得して、それから「ユーザーID」を復元してユーザーを特定することにより、接続を維持する
  • ユーザー識別子は暗号化されているので、他のユーザーのユーザー識別子を生成してなりすますのは困難

セッションについて

  • セッションIDの生成方法はHTTPの仕様として定まっていない。サーバー側の実装に依存する
  • 各プログラム言語にはメジャーなセッションライブラリがあり、セッションID生成には、それらを使うことが多い
  • それらのライブラリの多くのデフォルトの実装は、セッションIDとしてユニークで推測しずらい値を生成し、それをキーとして「ユーザーID」などのユーザーデータを紐付けて、ローカルファイルやメモリ上にキーバリューデータとして保存しておく
  • そして、ブラウザーからアクセスがあった場合は、クッキーからセッションIDを読み取り、セッションIDをキーに、キーバリューデータから該当するユーザーデータを復元する
  • キーバリューデータをサーバーのローカルファイルやメモリに保存するため、サーバーを複数設置して負荷分散させた場合、接続毎に接続先のサーバーが変わってしまうので、セッションが維持できなくなってしまう
  • なので、どのサーバーにアクセスしても適切なユーザーデータが復元できるように、キーバリューデータをローカルではなく、データベースに格納するようにすることも多い

感想など

ユーザー認証するサイトを作る必要がありました。

こういうセキュリティに絡む部分は自分で実装せず、ライブラリに任せてしまうのがいいのですが、ライブラリを使うにしても、概念は知っておいた方がよく、このあたりがよく分かってなかったので、備忘録として自分メモを作りました。

シングルページアプリケーションの場合でも、セッションIDとクッキーが、トークンとAuthヘッダーに代わっただけで、暗号化されたIDから情報を取り出して確認するという、基本的な考え方は同じですね。