Yuhan.jp

Cookie を用いたセッション管理

2025年11月22日(土)

はじめに

最近、お仕事の影響でマルチタスク&脳みそフル回転で、仕事の後、頭を使うことが何もできない無気力人間になってしまっており、元々、あんまり更新できていないサイトなのに、さらに更新が滞っておりました。

今回は、Cookie についてまとめたいと思います。食べる方のクッキーじゃないです。

雰囲気でやってましたが、利用機会の多いものなので、きちんと理解した方がいいと自分のアウトプットを目的としてまとめています。

ある程度調べながら書いてはいますが、筆者は技術的にまだ赤ちゃんも同然なので、微妙に誤りや認識違いなどがある可能性があります。

保険をかけるために、先に謝っておきます。ごめんなさい。

Cookie とは

そもそも、「Cookie とはなんぞや?」というところから。

Cookie とは、簡単にいうと「ブラウザに保存されるデータ」のことで、サーバーとWebブラウザ間での通信で利用されます。

よくある用途としては、ECサイトなどの認証機能のあるWebサイトにログインした後、「ユーザーがログインしているかどうか?」を判定するために、Cookie が利用されます。

そのほかにも、ユーザー設定などを保持する用途やトラッキングなどにも用いられます。

Cookie の名前の由来は、お菓子のクッキーと言われています。調べたところ、マジッククッキー?なるものが由来という説がありますが、諸説ありそうです。

より正確で詳細な解説が必要な場合は、MDNのサイトを。

参考:https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/Cookies

SessionStorage や LocalStorage との違い

ブラウザに保存できるデータストレージというと、SessionStorage や LocalStorage などもあります。

これらは Cookie とよく比較されますが、SessionStorage と LocalStorage は、Web Storage API の仕組みとして提供されるものであるのに対して、Cookie は別の概念になります。

ぞれぞれの特徴や性質から、用途に合わせて利用されます。

困った時は、MDN のサイトを読みましょう。

参考:https://developer.mozilla.org/ja/docs/Web/API/Web_Storage_API

SessionStorage とは

SessionStorage はその名前の通り、セッション単位で有効であるという特徴を持ったストレージです。

わかりやすくいうと、SessionStorage に保存されたデータは、タブやウィンドウを閉じると消えてしまいます。また、タブ間やウィンドウ間でデータを共有することはできません。

フォームに入力されたデータなど、長期間の保存を必要としないデータのための一時保存領域として利用されます。

LocalStorage とは

LocalStorage は、永続的にデータを持つことができるストレージです。

ウィンドウやタブを閉じてもデータが残り、ウィンドウやタブ間でデータの共有が可能です。

SessionStorage とは異なり、長期間保存したいデータを格納するのに用いられます。

Cookie、SessionStorage、LocalStorage の比較

 

Cookie

SessionStorage

LocalStorage

概要

ブラウザに保存されるデータ。

セッション単位で有効なブラウザのデータストレージ。

永続的に有効なブラウザのデータストレージ。

サイズ

1つ当たり約4KB

 

5〜10MB

※ブラウザによる。

5〜10MB

※ブラウザによる。

特徴

タブやウィンドウ間で共有できる。

有効期限が設定されていない場合は、ブラウザを閉じると消える。

タブやウィンドウ間で共有できない。

タブやウィンドウを閉じると消える。

タブやウィンドウ間で共有できる。

タブやウィンドウを閉じても消えない。

主な利用用途

ログイン後のセッション管理

ユーザー設定やトラッキング

入力データの保持

ECサイトのカート機能

ユーザー設定

Cookie の確認方法

Cookie (SessionStorage や LocalStorageも)は、ブラウザの開発者ツールから確認が可能です。

私は、Chrome 使いなので、Chrome のスクリーンショットで説明します。

Chrome で、好きなサイトにアクセスして、以下のショートカットで開発者ツールを立ち上げます。

Ctrl + Shift + i(Macなら Cmd + Option + i)

ショートカットではなく、ブラウザのメニューから「その他のツール」->「デベロッパーツール」で立ち上げることもできます。

開発者ツールを起動すると、こんな感じの表示が出てくると思います。

上部のタブから「Application」をクリックすると、ブラウザのストレージが確認できるため、ここから Cookie に何が格納されているのか確認することができます。

Google Chrome(Webブラウザ)のデベロッパーツールのApplicationタブ

余談ですが、ログアウトするなりシークレットウィンドウ使うなりすればマスキングいらないのはわかってるんですけど、マスキングする手間の方が個人的に楽という、よくわからない矛盾でスクショのマスキングをしています。

Cookie を使ったセッション管理

ここでは、セッション管理(ログイン状態の判別)における Cookie の利用に焦点を当ててまとめます。

考慮することとして、以下のようなポイントがあるかと思います。

  • Cookie に何を保存するのか?
  • どのように保存するのか?
  • 保存したデータをいつ、どのように削除するのか?

イメージ

最初に貼った図の再掲です。

セッション情報をCookie に保存

サーバーは、ログイン状態を管理するために利用するセッション情報(IDやトークンなど)を発行します。

発行したセッション情報を Cookie として保存するために、Set-Cookie ヘッダー を利用します。

Set-Cookie ヘッダー

サーバーからWebブラウザに送るレスポンスに付与することで、データを Cookie として保存してくれます。

Set-Cookie: <cookie-name>=<cookie-value>

下の例だと先頭の sessionId=xxxxxxxxxx が Cookie の名前(sessionId)と値(xxxxxxxxxx)で、それ以降の部分は Cookie の設定に当たる属性です。

Set-Cookie: sessionId=xxxxxxxxxx; SameSite=Strict; Secure; HttpOnly

Cookie の名前は任意のものを設定することができますが、一部利用不可な文字があります。

参考:https://developer.mozilla.org/ja/docs/Web/HTTP/Reference/Headers/Set-Cookie

Set-Cookie ヘッダーで利用できる属性には、以下のようなものなどがあります。

  • Domain
  • HttpOnly
  • Expire
  • Secure
  • SameSite

Domain

Cookie が送信されるドメインを定義します。

指定したドメインのサブドメインでも Cookie が利用できるようになります。

未指定の場合は、デフォルトで Cookie の送信元ドメインが設定されますが、その場合はサブドメインでは Cookie の利用ができません。

HttpOnly

JavaScript が Cookie にアクセスできないようにするための属性です。

クロスサイトスクリプティング(XSS)を緩和するために設定します。

(余談)このような個人サイトに、リンクや名前を載せることが許容されるかわからなかったので記載は控えますが、クロスサイトスクリプティング対策としてHttpOnly 属性がどれほど効果があるのかは、デモを用いた解説動画が Youtube にあり、とても勉強になりました。

Expires

Cookie の有効期限を設定します。以下のような形式で指定します。

Expires=Mon, 01 Jan 2025 00:00:00 GMT

有効期限が設定されていない Cookie は セッションクッキーとなり、ブラウザを閉じた時に削除されます。(デフォルト)

セッション復元機能により、タブが復元された場合はセッションクッキーも復元されます。

同じく Cookie の寿命を設定する属性として Max-Age があります。 Expires の方が Max-Age よりも長い期間の指定ができますが、両方設定されている場合は、 Max-Age の設定が優先されます。

Secure

HTTPS 通信のみに Cookie の送信を許可する設定です。

これを設定すると、HTTP 通信では Cookie の送受信ができなくなります。

SameSite

クロスサイトにおける Cookie の送信を制御する設定です。

以下のいずれかを設定します。名前の通り、Strict > Lax > None の順でセキュリティレベルを示しています。

Strict:同じサイト間でのみ Cookie の送信を許可します。

Lax:同じサイト間での Cookie の送信を許可し、GET リクエストなど特定の条件のみでクロスサイトでの Cookie の送信を許可します。

None:クロスサイトでも Cookie の送信を許可します。None を設定する場合は、Secure 属性が必須になります。

Domain と SameSite について

Domain 属性と SameSite 属性は似ているのですが、以下のように異なる制御を行う設定です。

Domain :サーバーがブラウザに Cookie を送る際に「どのドメインに属するか」を指定し、指定されたドメインとサブドメインでその Cookie が利用できる。(HTTP標準仕様)

SameSite : ブラウザがサーバーに Cookie を送る際に「どのようなリクエストに含めるか」を制限する。(ブラウザ固有のセキュリティ機能)

↑の説明があんまりわかりやすくないのですが、設定する上では下記の認識に落ち着きました。

Domain は複数ドメインで共有したい Cookie に設定して、特に必要がなければ設定しない。

SameSite は Strict もしくは Laxを設定。None は基本的には使わないことが推奨。(クロスオリジンでは None にするしかない?)

調べてなんとなく雰囲気はわかったんですが、言語化がむずかしい......。ちょっと、また別の機会に掘り下げて言語化しようと思います。

リクエストにおける Cookie の利用

サーバーへのリクエスト時に Cookie として保存されたセッション情報を含めることで、サーバー側でログイン状態を判別するのに利用することができます。

Cookie を使う際に引っかかりがちなところとして、CORS の設定があります。

※CORSの説明だけで1つの記事になってしまいそうなので、Cookie に関連するところをかいつまんでまとめます。

Cross-Origin Resource Sharing(CORS)

Cross-Origin Resource Sharing(オリジン間リソース共有)略して CORS とは、その名前の通り、異なるオリジンの間でリソースを共有するための仕組みです。

オリジンとは、「ドメイン+プロトコル+ポート番号」 の組み合わせです。

Cookie だけでなく画像などさまざまなリソースにおいて、別のオリジンにあるものを利用する場合に設定が必要になります。

参考:https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/CORS

若干正確じゃないのですが、下記のようなイメージです。

CORS は、異なるオリジン間でリソースを共有する際のセキュリティリスクを軽減するために必要な仕組みです。

初めて CORS エラーに躓いた時それはもう苦しめられたのと今でも躓くので憎らしく思うこともありますが、この仕組みのおかげで不正利用や攻撃などのリスクを抑えて安全に利用できることを忘れてはいけません。(戒め)

Cookie で必要な CORS 設定のポイント

本題ですが、Cookie を使う際、同一オリジンで完結するのであれば CORS を意識する必要はありません。CORS はクロスオリジンでリソースを共有するための仕組みなので。

クロスオリジンではCORS の適切な設定がされていないと、Cookie の利用が許可されません。

Cookie 利用のための CORS 設定のポイントは以下の3つだと思います。

  • Access-Control-Allow-Origin ヘッダーによる明示的なオリジンの許可(*は不可)
  • Access-Control-Allow-Credentialsヘッダーの利用
  • クライアント側でリクエストに認証情報を含める設定

CORS では、サーバー側で CORS ヘッダーを追加して異なるオリジンからのアクセスを許可していることを設定する必要があります。

CORSヘッダー

主に設定が必要になる CORS ヘッダーは下記の通りです。

Access-Control-Allow-Origin

すべてのCORSリクエストで必須のヘッダー。

許可するオリジンを指定します。

* ですべてのオリジンを許可することができますが、Cookie を使う際には後述の Access-Control-Allow-Credentials: true を設定するため、*は許容されません。

Access-Control-Allow-Methods

許可するHTTPメソッドを指定します。

POST や PUT、DELETE などのリクエストでは、プリフライトリクエストが発生するため、このヘッダーが必要になります。

Access-Control-Allow-Headers

カスタムヘッダーを使う場合に必要な設定で、許可するヘッダーを指定します。

Content-Type や Authorization などのデフォルトで許可されていないヘッダーを使いたい場合などに指定します。

Access-Control-Allow-Credentials

Cookie や認証情報を送信する時に必要になるヘッダーで、クロスオリジンリクエストでこれらを使いたい場合に trueを設定します。

クライアント側の設定

クライアント側では、リクエストに Cookie を含めるための設定が必要です。

fetch の場合。

fetch('https://api.example.com/data', {
  credentials: 'include'
});

axios の場合。

axios.get('https://api.example.com/data', {
  withCredentials: true
});

おわり

さらっと軽くまとめるつもりが、結構色々書いてしまった。

個人的に、この辺りは勉強していて楽しいです。

都度都度調べては、しばらく期間が開くと忘れる、を繰り返してしまうので、しっかり理解に落とし込んで一度学んだことは定着させて使いこなせるようになりたいですね。

最近、本当に何もできていなかったので、久しぶりに勉強が楽しいという感覚を思い出している気がします。

Cookie ってたくさん書いていたから、クッキーを食べたくなりました。