実務経験1年5ヶ月でセッションとCookieを改めておさらいする

## はじめに

[個人ブログ](https://yutaro-blog.net/)に技術記事を書くようになってから全然Qiitaに書いてないので久しぶりに書きます。

最近はTypeScript/Nuxt.js/Next.js/LaravelでSPAの開発をしています。
PM、PL寄りのタスクも（まだまだですが）少しずつやり始めました。

ふとした時に「セッションとCookieについて意外とフワッとした理解しかできてないかもしれない...」と思ったので、（今更ですが）この機会にしっかり調べてまとめておこうと思い、記事を書いています。

というわけでタイトルのとおりセッションとCookieについて、まとめます。

（個人ブログには当該記事を書いているのですが、Qiitaの方が見られやすいかなと思いこちらでも残します）

## Cookieについて

### Cookieとは

Cookieをかなりざっくり表現すると**クライアント（Webブラウザ）に保存されたデータのこと**です。

色々な技術書、記事を調べてみるとこのように書いていました。

> cookieは“Webサイトとユーザー間でやり取り・保存されるアクセス情報”のこと。
https://data.wingarc.com/what-is-cookie-23546

> Cookieは、クライアントに保存された情報のことです。
https://qiita.com/7968/items/ce03feb17c8eaa6e4672

> Webブラウザに保存してもらいたい情報
イラスト図解式 この一冊で全部わかるWeb技術の基本

> ウェブブラウザに保存された情報
https://ja.wikipedia.org/wiki/HTTP_cookie

大体同じことを書いているので、先ほど書いた通りの理解で良いかと思います。

### Cookieの特徴

他の特徴についても調べたので以下にまとめます。

:::note
- CookieはサーバーからのHTTPレスポンスのSet-Cookieヘッダーを使用してWebブラウザに送られ、保存される
- 保存されたCookieはクライアントからサーバーにリクエストするたびに自動送信される
- 有効期限が設定されていないCookieは、Webブラウザが閉じられると一緒に削除される（「セッションCookie」とも言う）
- 有効期限が設定されたCookieは、期限が過ぎるまではWebブラウザを閉じても削除されない
- 「クッキー名＝値」の形（1つのクッキーは4KBまで）
- ブラウザによって保持できる数が異なる
- 最近のタブ型ブラウザでは、同じPC上でタブやウィンドウを複数表示してもCookieは共有される
- CookieはWebブラウザの識別にも使われるので、他人に盗まれてなりすましをされる可能性がある
:::

（あんまり発生しない事案だと思いますが、共用のPCでECサイトにログインしていて、ログアウトせずPCの利用をやめた後、別の人がPCを使ったらECサイトにログインしたままの状態になっているということもあり得なくないですもんね…想像するだけで怖い…）

したがって、セキュリティ上の観点からECサイトのような金銭が絡むサービス等では、有効期限がなくWebブラウザを閉じた時に削除されるセッションCookieを使うのが一般的です。

他にも特徴はありますが、調べるとキリがないので個人的にはひとまずこれくらいでOKかなと思います。

## セッションについて

### セッションとは

セッションをざっくり言うと**一連の処理の始まりから終わりまでを表す概念**です。

Cookie同様、どのような表現・説明がされている色々調べてみました。

> 一連の処理の始まりから終わりまでを表す概念
https://qiita.com/7968/items/ce03feb17c8eaa6e4672

> WebブラウザとWebサーバーのやりとりにおいて、一連の関連性のある処理の流れ
イラスト図解式 この一冊で全部わかるWeb技術の基本

> 「サーバ内に情報を保存し、複数ページ間で共有する」仕組みのこと
https://kanda-it-school-kensyu.com/php-basic-contents/pb_ch11/pb_1103/

> 一連のインタラクティブな操作のこと
https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3

「一連の処理の始まりから終わりま」でというのは例えば

- ログインしてからログアウトするまで
- HTTP通信の接続を確立したから遮断するまで

このように色々な意味で使われます。

（前者はアプリケーションの状態としてのセッション、後者はHTTP通信としてのセッションを表します。セッションという言葉は割と意味が広いことがわかります。）

### セッションの特徴

セッションの特徴を下にまとめます。

:::note
- HTTPのセッションは「セッションID」を使って同一のセッションを管理する
- セッション情報はサーバーに保存されることが多い
- セッションIDはCookieに保存し、リクエストヘッダに格納してPOSTメソッドで送受信したり、URLに埋め込んでGETメソッドで送受信したりする
- Cookieを利用することでセッション（一連の処理）を実現できる＝ステートレスをステートフルにできる
- セッションはWebブラウザを閉じるまで保存する
- リンクなどでページを移動しても内容を保持することができる
- セッションIDのやりとりはCookieを用いる方法が一般的だが、Cookieが使えるかどうかはブラウザによるため、GETパラメータを用いてやりとりするなど他の方法をとるケースもある(セキュリティ上は非推奨)
- モダンブラウザでは、同一PC上では、必ず同じセッションとなる（IE7以前では、新規ウィンドウを開かない限り異なるセッションとなる）
- HTTPのセッションは「セッションID」を使って同一のセッションを管理する
:::

参考までに、セッションの保存先は上記のとおりサーバーが一般的ですが僕が普段の業務で使っているLaravelではセッションの保存先を複数の選択肢の中で変更することできます。（以下記事参照）

https://readouble.com/laravel/8.x/ja/session.html

## セッション＋Cookieでできること

セッションとCookieについて概要をまとめましたが、この2つの技術は併せて使われることがほとんどです。

では、2つを組み合わせることで何ができるかというと**「ステートレスなHTTPをステートフルにする」**です。

もう少し噛み砕いて書くと、

- Aさんがログインしていること
- Bくんが商品Pをカートに入れていること

このようなアプリケーションの状態（セッション状態とも言う）を維持できるようになります。

この2つの技術を使ったアプリケーション状態の維持は以下のような（認証が必要な）アプリケーションなどで使われます。
（というかこの世の中のサービスのほとんどで使われているのでは？と思います）

- ECサイト
- 転職サイト
- SNS


「じゃあセッションとCookieを組み合わせることでステートフルにしているのか？」はこの次に書くとして、わかっている方も多いと思いますが、ステーレスとステートフルの違いについてポピュラーなハンバーガーショップを例にして軽く触れておきます。
（見飽きた、という方は飛ばしてください）

### ステートレス（HTTPの標準仕様）


```
客「ハンバーガーセットをお願いします。」

店員「ハンバーガーセットですね。ドリンクは何にしますか？」

客「ファンタでお願いします」

店員「ファンタですね。サイズは何にしますか？」←ここで既にハンバーガーセットではなくドリンク単品になっている

客「Mでお願いします。」

店員「M？え？何がですか？」

客「え…」
```

### ステートレス（セッション+Cookie使用）

```
客「ハンバーガーセットをお願いします。」

店員「ハンバーガーセットですね。ドリンクは何にしますか？」

客「ファンタでお願いします」

店員「ハンバーガーセットのドリンクはファンタですね。サイズは何にしますか？」

客「Mでお願いします。」

店員「かしこまりました。ハンバーガーセットのドリンクはMサイズのファンタですね。」

客「はい。以上で。」
```

このような感じでステートレスだと1回の会話のキャッチボールで前提条件が全てリセットされるので正しく注文することができません。

（厳密には「ハンバーガーセット1つで、ドリンクはファンタで、サイズはMでお願いします。注文は以上です。」という感じで言えば正しく注文することはできます）

## Cookieを使用したセッション管理の仕組み

それではCookieを使ったセッション管理（アプリケーションの状態保持）の仕組みを分かりやすいように図でまとめます。

今回は「WebアプリケーションがA君がログインしているという状態を維持する」ことを例にして進めます。

### セッションファイルを作成する
まずはA君が初回ログイン（HTTPリクエスト）をします。ログインに成功するとWebアプリケーションはサーバーにセッションファイルを作成し、セッションIDとログインしたユーザー（A君）の情報をセッションファイルに記録します。（今回はユーザーIDのみ）

![セッションとCookie-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/ad243810-5e5c-3328-daf1-155f80a795c7.jpeg)


### クラアイントにCookieを保存する
リクエストを受けたサーバーはクライアント（Webブラウザ）にHTTPレスポンスを返します。この時ににSet-Cookieレスポンスヘッダーを使って、sessionidという名前で値がセッションIDである9reifwjgkrnrqfuvoijqfiのCookieをWebブラウザに保存するように指示します。レスポンスを受け取ったクライアントは指示通りCookieを保存します。
（Cookieの名前は例です。セッションIDも適当に書いた乱数です）


![セッションとCookie-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/6ae62a1b-cdf4-bfe7-8fa8-bcd5226936d8.jpeg)


### サーバーでリクエストしたユーザーを判別する
WebブラウザにCookieを保存した状態で再度サーバーにリクエストするとCookieも自動的に送ります。リクエストを受け取ったサーバーはCookieからセッションIDを取り出し、セッションファイルに照合をかけ、ユーザーの判別（A君であること、ログイン済みであること）をします。

![セッションとCookie-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512695/c73471da-3f19-ddfa-c2b4-438c5f4338a3.jpeg)

このようにしてセッションとCookieを使うことでWebアプリケーションが「ユーザーがログインしている」という状態を維持することができます。（ステートフルにできる）

## 最後に

セッションとCookieに限らずですが、駆け出しの時や実務経験が浅い時に勉強していたことって結構忘れれるし、それをある程度仕事ができるようになってから改めて復習・おさらいすると当時とは比べ物にならないくらい理解が進むことってあるなと感じました。

定期的に基礎に戻って深掘りしたい。

個人ブログはこちらです。よかったら覗いてみてください。

https://yutaro-blog.net/

※明らか間違っている内容があればコメントください。