Cookieとセッション管理


Cookieやセッション管理といったWebアプリケーションの基本技術について改めて調べてまとめた。
『[HTTPの教科書](http://www.shoeisha.co.jp/book/detail/9784798126258)』、『[プロになるためのWeb技術入門](http://gihyo.jp/book/2010/978-4-7741-4235-7)』が主な情報元で、[RFC6265](https://tools.ietf.org/html/rfc6265)も一部見ている。

## Cookieとは
HTTPにおいてWebブラウザとWebサーバ間で状態を管理するプロトコル、またはそこで用いられるWebブラウザ上に保存された情報のこと

※ 参考：[Cookieとは｜HTTP Cookie｜クッキー - 意味/解説/説明/定義 ： IT用語辞典](http://e-words.jp/w/Cookie.html)


## Cookieの目的
ステートレス（状態を維持できない）なプロトコルであるHTTP上で、状態管理ができるようにすること

## Cookieの仕組み
まず、サーバが`Set-Cookie`という名前のフィールドをHTTPヘッダに載せてレスポンスを返す。Cookieとしてクライアントに保存して欲しい情報を、この`Set-Cookie`フィールドの値として設定する。
レスポンスを受け取ったクライアントはCookieをブラウザに保存する。そして、それ以降のリクエストには受け取ったCookieをそのままリクエストするようになる。

※ Cookieを載せてリクエストするURLの範囲は`Set-Cookie`の属性値で指定され、その値に従う
※ Cookieには有効期限があり、有効期限が切れたCookieは消滅し、リクエストに載らない

![cookie&session.001.png](https://qiita-image-store.s3.amazonaws.com/0/2813/6f120ec2-9a44-69a0-1506-1b28857c4f98.png "cookie&session.001.png")

### 例：ユーザの訪問回数を表示する
ユーザが何回サイトを訪問したかを表示したい場合に、Cookieを使うとどのような流れになるか追う。
→ Cookieを使って、ユーザの訪問回数という「状態」をどのように管理するか

１．ユーザがリクエストを送る。これが初回のアクセスだとする。このとき、クライアントはCookieを持っていない

```リクエスト(1)
GET /index.html HTTP/1.1
Host:example.com
```

２．サーバは「Set-Cookie」というフィールドをレスポンスヘッダに載せる。Cookieの中にはアクセス数を示す「visit=1」が含まれている。レスポンスボディには、「訪問回数:1」で構築したHTMLを載せる。

```レスポンス(1)
HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Set-Cookie: visit=1; path=/; expires=Wed, 10-Oct-12 07:12:20 GMT

<html>
<head></head>
<body>
  <p>訪問回数:1</p>
</body>
</html>
```

３．レスポンスを受け取ったクライアント（Webブラウザ）はCookieを保存する

４．再度ユーザがアクセスするとき、Webブラウザは保存したCookieの値（この場合、「visit=1」）を自動的に載せてリクエストを行う

```リクエスト(2)
GET /index.html HTTP/1.1
Host:example.com
Cookie: visit=1
```

５．サーバはリクエストに`visit=1`というCookieを見つける。これは前回までの訪問回数なので、visitに1を足して再度`Set-Cookie`フィールドをヘッダに載せる。レスポンスボディには、`Set-Cookie`フィールド同様にvisitの値に1を加えて構築したHTMLを載せる。この場合は「訪問回数:2」となる。

```レスポンス(2)
HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Set-Cookie: visit=2; path=/; expires=Wed, 10-Oct-12 07:13:20 GMT

<html>
<head></head>
<body>
  <p>訪問回数:2</p>
</body>
</html>
```

## Cookieのためのヘッダフィールド
|ヘッダフィールド名|説明|ヘッダ種別|
|:--|:--|:--|
|Set-Cookie|状態管理開始のためのCookie情報|レスポンス|
|Cookie|サーバから受け取ったCookie情報|リクエスト| 
※ 参考：HTTPの教科書　6.7 Cookieのためのヘッダーフィールド

### Set-Cookieヘッダフィールド

|属性|説明|
|:--|:--|
|NAME=VALUE|Cookieにつける名前とその値（必須）|
|Expires=DATE|Cookieの有効期限（デフォルトはブラウザを閉じるまで）|
|Max-Age=DATE|クッキーの残存期間を秒数で指定する。例えば`Max-Age=100`であれば100秒後に消滅する|
|Path=PATH|Cookieの適用対象となるサーバ上のパス（デフォルトはドキュメントと同じパス）|
|Domain=DOMAIN|Cookieの適用対象となるドメイン名（デフォルトはCookieを生成したサーバのドメイン名）|
|Secure|HTTPSで通信している場合にのみCookieを送信するオプション|
|HttpOnly|CookieをJavaScriptからアクセスできないように制限するオプション|

※ 参考：HTTPの教科書　6.7 Cookieのためのヘッダーフィールド
※ 参考：http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html#section-5.2

## セッション管理
セッションとは、一連のインタラクティブな操作のこと。例えばECサイトには、商品を探し、カートに入れ、購入するという一連の流れがある。このように同一利用者からのアクセスを関連性のある一連のアクセスとして扱いたい場合、Cookieを使ってセッション管理が行われる。

- クライアントはWebサイトにログインする。このとき、ユーザIDとパスワードをサーバに送信する
- サーバはセッションIDを生成し、Cookieに載せて返す
	- 例：`Set-Cookie: PHPSESSID=028a9x...`
	- なりすましを防ぐため、セッションIDは特定しにくい値にする必要がある
- 以降、クライアントはCookieにセッションIDを載せてリクエストすることでセッションの維持ができるようになる


## セッション情報の保存方法
CookieとしてリクエストしてもらうセッションIDから、どのようにしてセッション情報（例えばユーザ名とかカート内の商品とか）を管理・保存しているのかを調べた。次のような方法があるようだ。

- ファイルに保存する
- Cookie内に暗号化して持つ
- MySQLなどのデータベースに保存する
- memcachedなどのKVSに保存する

※ 参考：[Railsのセッション管理方法について - Programming log - Shindo200](http://shindolog.hatenablog.com/entry/2014/11/02/164118)
※ 参考：[Rails セキュリティガイド | Rails ガイド](http://railsguides.jp/security.html)

## その他気になって調べたこと色々
- Cookieの最大サイズ
	- RFCでは、4096バイト以上を提供するべきであるとしている
	- [RFC 6265 — HTTP State Management Mechanism （日本語訳）](http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html#section-6.1)
- 1ドメインあたりのCookieの最大個数
	- RFCでは50個以上保持できるようにすべきであるとしている
 	- [RFC 6265 — HTTP State Management Mechanism （日本語訳）](http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html#section-6.1)
- Cookieとドメイン
	- CookieのDomain属性は、そのCookieの生成元サーバを内包するスコープを指定しない場合、無視される。例えば、`example.com`から受信されたCookieのDomain属性に`yahoo.co.jp`が指定されているような場合、これは無視される。
- Cookieの有効期限
	- Max-Age属性もExpires属性も指定されていない場合はブラウザを閉じるタイミングでCookieが消滅する
	- Cookieの最長/最短の有効期限は調べてみたがよくわからず。無期限とかは無理っぽい。
	- [RFC 6265 — HTTP State Management Mechanism （日本語訳）](http://www.hcn.zaq.ne.jp/___/WEB/RFC6265-ja.html#section-4.1.2.2)


## 実際にCookieの値を見るときに役立ったツール
Chrome使ったのでChrome関係ばかり

- Chrome DevTools
- Live HTTP Headers（Chrome拡張）
- EditThisCookie（Chrome拡張）