保存場所を比較する軸
ブラウザ側の保存場所を理解するときは、次の4つの軸で見ると整理しやすくなります。
- JavaScriptから読めるか
- サーバへ自動で送られるか
- どのタイミングで消えるか
- 認証情報を置いてよいか
まず全体像です。
| 保存場所 | JSから読める | 自動送信 | リロード | タブ終了 | ブラウザ終了 |
|---|---|---|---|---|---|
| メモリ変数 | 読める | なし | 消える | 消える | 消える |
| sessionStorage | 読める | なし | 残る | 消える | 消えることが多い |
| localStorage | 読める | なし | 残る | 残る | 残る |
| Cookie | 条件次第 | あり | 残る | 設定次第 | 設定次第 |
メモリ保存
メモリ保存とは、JavaScriptの変数や状態管理ライブラリにだけ値を持つことです。
let accessToken = null;
function setToken(token) {
accessToken = token;
}
Reactであれば、useState や状態管理ストアにだけ持つイメージです。
const [accessToken, setAccessToken] = useState(null);
メモリ保存の特徴は、ページをリロードすると消えることです。これは不便ですが、トークンを長くブラウザに残さないという意味では利点でもあります。
sessionStorage
sessionStorage は、タブ単位の保存場所です。
sessionStorage.setItem("wizard_step", "2");
同じタブでリロードしても残ります。しかし、タブを閉じると消えます。
フォームの一時入力、画面遷移中だけ必要な状態、タブ内だけで完結する作業には向いています。
ただし、JavaScriptから読めるため、高価値な認証トークンを置く場所としては注意が必要です。
localStorage
localStorage は、同じオリジンで長く残る保存場所です。
localStorage.setItem("theme", "dark");
localStorage.setItem("sidebar", "collapsed");
ブラウザを閉じても基本的に残ります。ユーザー設定やチュートリアル既読フラグなどには便利です。
一方で、アクセストークンやリフレッシュトークンを置くと、XSS時に盗まれやすくなります。
注意: localStorage は永続性が高く、JavaScriptから読めます。便利な分、漏れたら困る値を置くと被害が長引きやすくなります。
Cookie
Cookie は、サーバが Set-Cookie で保存を依頼し、ブラウザが条件に合うリクエストへ自動で送るデータです。
Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Path=/
HttpOnly が付いていないCookieはJavaScriptから読めます。
console.log(document.cookie);
HttpOnly が付いているCookieはJavaScriptから読めません。しかし、ブラウザはHTTPリクエストに付けられます。
認証セッションでは、この性質が重要です。
認証情報との相性
認証情報を置く場所として見ると、判断は次のようになります。
| 保存場所 | access token | refresh token | セッションID |
|---|---|---|---|
| メモリ | 短命なら候補 | 不向き | 不向き |
| sessionStorage | 慎重に検討 | 不向き | 不向き |
| localStorage | 原則避けたい | 避けたい | 避けたい |
| HttpOnly Cookie | 構成次第で候補 | 要件次第 | 向いている |
| サーバ側ストア | 向いている | 向いている | 向いている |
近年のBFF構成では、ブラウザには HttpOnly Cookie のセッションIDだけを持たせ、アクセストークンやリフレッシュトークンはサーバ側に閉じ込める設計がよく使われます。
リロードで消えることは悪いことではない
初心者のうちは、リロードしてログイン情報が消えると「不便だからlocalStorageに入れよう」と考えがちです。
しかし、認証情報は便利に残せばよいものではありません。長く残るほど、盗まれたときの被害も長く残ります。
たとえば、メモリ上に短命アクセストークンだけを置き、リロード後はサーバ側のセッションやリフレッシュ処理で復元する設計があります。これは実装が少し複雑ですが、ブラウザに高価値トークンを長く置かないという利点があります。
ポイント: 認証設計では「消えないから便利」だけで判断しません。「盗まれたら何ができるか」「どれくらいの期間使えるか」で判断します。
まとめ
ブラウザの保存場所は、便利さとリスクがセットです。
- メモリ保存は短命で、リロードで消える
- sessionStorage はタブ単位で残る
- localStorage は長く残り、JavaScriptから読める
- Cookie はサーバへ自動送信され、HttpOnlyならJavaScriptから読めない
認証情報では、保存場所の選択がセキュリティ設計そのものになります。
参考リソース
- 公式ドキュメント - sessionStorage / localStorage / Cookie / メモリ保存の違い を確認するための一次情報