2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CBcloudAdvent Calendar 2019

Day 24

Cookieの仕組み

Last updated at Posted at 2019-12-25

CBcloud Advent Calendar 2019の24日分の記事になります。

Cookieとは

簡単に言えば、Cookieとはウェブサイトの情報をブラウザで保存する仕組みです。
HTTPのヘッダーをインフラとして実装されていて、最新の仕様書はRFC6265です。

主な流れ

  1. ブラウザ側
    • ウェブサイトに向けてHTTPリクエストを送信する
  2. サーバー側
    • HTTPヘッダにSet-Cookieヘッダをセットしてレスポンスを返す
      • Set-Cookie: LAST_ACCESS_TIME=15:30
  3. ブラウザ側
    • レスポンスのSet-Cookieヘッダの値を保存する。
    • 次回アクセス時には次のような形式でリクエストを送信する
      • Cookie: LAST_ACCESS_TIME=15:30

なにが嬉しいのか

以上のような非常に単純なやりとりを経ることによって、サーバー側はこのクライアントが最後にアクセスしてきた時間を知ることができます。
HTTPはステートレスを基本とした仕組みですが、Cookieをうまく使うことによってステートフルであるかのようなアプリを作ることができます。
もちろんブラウザ上でもJavaScriptを通して取得することが可能です。適当なウェブサービスで開発者ツールを開き、下記のコードを打てばString型でCookieが格納されていることが分かります。

console.log(document.cookie)

アンチパターン

便利な機能ですが、いくつかの制約からアンチパターンももちろん存在します。
 まず永続性の問題です。ブラウザの設定によってはサーバーからのSet-Cookieヘッダを無視することもありますし、履歴消去などで一緒に削除されることもよくあります(実際消した事ある人も多いはずです)。
 容量の問題もあります。最大容量は4kbです。通信のたびに毎回HTTPのヘッダに付与されるので単純に通信量が増大します。
 セキュリティにも問題があります。HTTPは常に平文で送受信されるため、クリティカルな情報を与えてしまうと漏洩の可能性があります。
また、SSL/TLSを利用していたとしてもユーザーから自由に見たり、編集したりできることも問題で、ログインに必要なIDなど書き換えられると誤作動につながるような情報を入れるのにも適しません。

制約を与える

Cookie周辺で使えるHTTPヘッダーは、Set-CookieCookie以外にもRFCによって定められたいくつかのヘッダーが存在します。

  • Expires,Max-Age クッキーの寿命を設定する
  • Domain ブラウザからCookieを送信する対象のサーバーを設定する
  • Path ブラウザからCookieを送信する対象のサーバーのパスを設定する
  • Secure https以外での通信のときはサーバーへCookieを送信しない
  • HttpOnly JavaScriptエンジンからCookieを隠すことができる(上記のようにdocument.cookieで取れなくなる)。

Cookieでのセッション管理

Web関係の入門書などでよくサンプルとして取り上げられる認証の仕組みとして、Basic認証とDigest認証がありますが、今現在もっともよく使われている認証の仕組みはCookieを用いたセッション管理だと思います。以下にCookieを用いたセッション管理の流れを書きます。

セッション管理の流れ

  1. ブラウザ側からIDとパスワードを送信します。
    • 注意点: 直接送信するため、SSL/TLSは必須です。
  2. サーバー側ではIDとパスワードで認証しセッショントークンを発行します。サーバー側はそのトークンをRDBなりKVSなりに保存します。そして、Set-Cookieにトークンを付与させてブラウザにレスポンスを返します。
  3. ブラウザは次回以降のアクセスではCookieヘッダーにサーバーから発行されたトークンを付与してリクエストを送ることによって、サーバーからログイン済のユーザーであることが識別できるようにします。

以上が簡単なセッション管理の仕組みになります。時間経過による自動ログアウトなどのよく見る仕組みは、上記のExpiresMax-Ageヘッダを使うことによって簡単に実装できることが分かります。

例: Ruby on Railsでの署名付きCookieによるセッションデータの保存

上述のような、RDBなどにセッション管理用のテーブルを用意しユーザーの認証をする素朴な実装は悪くはないのですが、実はRailsなどのようなWebアプリケーションフレームワークは大抵の場合セッションストレージ機能を備えており、自前で実装する必要はないことがほとんどです。
Railsのセッションストレージ機能で用いられるActionDispatch::Sesstion::CookieStoreは、delete_sessionload_sessionnewの3つしかメソッド持ちませんが、ブラウザに対して改ざんされないように電子署名付きのCookieを送信します。
ブラウザ側がそのCookieをRails側に再送すると、Railsは署名を確認します。ブラウザは何も特別なことはしておらず、署名も確認もRails側で行います。
この仕組みを用いることによるサーバー側のメリットは、データを保存する仕組みが必要ない点です。マイクロサービスにおいても、暗号化の仕組みだけ共通化しておけば、別にデータストアを立てる必要なくセッションデータを読み書きできるようになります。

おわりに

今回はサックリとまとめてしまいましたが、Cookieの歴史はWebセキュリティの歴史といってもいいほど試行錯誤がつまっており、Webアプリ作ってご飯を食べているWebエンジニア各位は一度しっかり時間を確保してCookieの仕組みなどを勉強してみるといいと思います。

参考図書

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?