Webアプリのセッション管理とデータ保存を学ぶ#2(社内勉強会)

2. Webサービスにおけるデータ保存(クライアントサイド編)

クライアント(ブラウザ)側でのデータ保存について、主流であるCookieをもう少し詳しく見てみましょう。

Cookie

CookieはHTTP仕様で定められているサーバーとクライアント間でHTTPリクエストを跨いだデータをやり取りできる方法の一つです。機能自体はサーバーがHTTPレスポンスの中で短い文字列データをクライアントブラウザ側に保存させ、クライアントブラウザが同じサーバーに通信する時に都度Cookieに保存された内容をHTTPリクエストに送信するといったシンプルな仕様です。
Cookieはクライアントに複数のHTTPリクエストを跨がって同じ文字列を送信させることができるので、ここにセッションIDを入れることでセッション管理を実現できるわけです。

具体的には、サーバーが返すHTTPレスポンスにSet-Cookieヘッダを含めておくと、サーバーが指定した情報がブラウザのCookieに保存されます。Cookie自体には文字列かできるのであれば何でも格納できるため、セッションIDはもちろん商品の入っているカートの状態なども保存できます。

ブラウザは以後同じサーバーにHTTPリクエストを送信するたびに、保存済みのCookieをサーバーに送信します。セッションIDをCookieに含めておけば、サーバーはそれを取り出すことで、HTTPリクエストがどのユーザーの送ったものなのかをセッションIDで判定できるようになります。

morimorihoge注)

CookieはRFC 6265 — HTTP State Management Mechanism (日本語訳)で仕様化されています(リンクは非公式日本語版)。
読んでみると分かりますが、有効期限やドメイン制限などのセキュリティ関連の機能を除くとかなりシンプルな仕様になっています。意識が高まったときに眺めてみるには手頃だと思います :)

Cookieの欠点

Cookieによるクライアント側でのデータ保存は広く定着している手法ですが、いくつかの問題があります。

  • Cookieに保存できるデータのサイズに制限がある (具体的なサイズはブラウザ依存)
  • Cookieはブラウザ側で書き換えられる(JavaScriptからも書き換え可能)
morimorihoge注)

これらの問題からCookieのデータはいつ壊れても大丈夫(システム上やり直しができる)、かつ改竄されても大丈夫なように設計しないといけません。

例えば、RailsにおけるデフォルトのCookieStoreのように、Cookieに暗号化済みのセッションデータを保存することでサーバー側にセッション変数を持たなくても良いようにする方法がありますが、データサイズが大きくなってくるとクライアントブラウザによっては受け入れられるCookie長を超えてしまい、複合不可能な文字列になってしまったりするケースがあり得ます。
サーバー側の開発時にもセッションストレージに何を使っているのかを意識しないと、こうした罠もあるということで。

他にも、セッションIDに推測可能なID(連番やユーザー名など)を使ってしまうとCookieを書き換えることで他人になりすますことが可能になってしまいますし、商品価格のような情報を一時的に入れるのは構いませんが、その値を注文処理でも信用してしまうとユーザー側で勝手に商品価格を書き換えて注文できてしまったりといったバグにも繋がります。

補足: HTML5のWeb Storage

Cookie以外のデータ永続化の方法として、HTML5では以下の2つのWeb Storageが仕様に追加されました。WebStorageはCookieとは違い、より大容量なデータを扱えるようになっているため保存可能なデータ量がCookieよりも大きくなっていますが、保存可能な最大サイズはブラウザの実装に依存しています。

  • SessionStorage: 現在開いているウィンドウやタブの中でのみ使える。閉じた時点でデータは破棄される。
  • LocalStorage: 永続的に保存可能。ブラウザを起動しなおしてもデータを引き継ぐことができる。

Web StorageはCookieとは違いクライアントがブラウザに対してJavaScriptを通して保存させるという手順を取るため、Cookieほどお手軽ではなく、サーバーサイドから書き換えたい場合にはクライアント側のJavaScript実装も必要です。

morimorihoge注)

Web Storageはある程度大きなデータを保持できることからSPA(Single Page Application)でのキャッシュといった利用が主かと思いますが、ユーザー側に見られても良いようなマスタデータのようなものを保管しておくことで、JavaScriptだけで実現できることの範囲を広げるといった利用も可能です。

本来この辺りはWeb SQL Databaseが使えれば良いのですが、主要ブラウザではChrome/Safariくらいしか対応しておらず、IE/Edge/Firefoxで利用できないので、まだまだ大手を振って使える感じはないですね。
※社内システムなどでブラウザを指定できる場合は別ですが

参考: モダンブラウザのストレージ容量と調査方法まとめ - HTML5 Rocks

なお、TechRachoのCookieをChromeブラウザで見ると次のような感じになります(デベロッパーツールの[Application]タブ)。

morimorihogeコメント)

Webの世界は「今動いているものとの後方互換性が大事」という文化が強かったため、今から見ると「なんでこんな制限があるんだろう?」と思う機能が多々あります。Cookieもそんな中の一つです。
それこそ15〜20年前くらいのガラケー全盛期ではCookieが利用できないブラウザというのもあったくらいなのですが、そんな中でも今ある機能を使ってなんとかするという方法が進化してきました。

昨今はPC/スマホ向けについてはバージョン更新の流れが速まり新しい機能も使えるのが当たり前になってきましたが、組み込み向けなどは使われる期間も長いため、レガシな機能についても仕様や制限を把握しておくこと自体は役に立つことがあると思います。
※そして得てして新しい機能のニーズはレガシな機能の延長線上にあるので、なぜその機能が必要とされてきたのかという文脈を知ることにもなります。

関連記事

Webアプリの基礎とさまざまな実行環境を理解する#1(社内勉強会)

Linuxのサービス起動周りとDockerとの関連を理解する#1(社内勉強会)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ