ブラウザの Cookie が意図せず消えてしまった、という件の対応メモ

PHP/JavaScript のプロジェクトで、いわゆる「お気に入り」機能を Cookie で実現している箇所があり、その機能についてユーザーから「お気に入り登録したのに後日確認すると消えていた」という旨の連絡がありました。意外な盲点だったので記録しておきます。

状況

まず、そのプロジェクトでは「お気に入り」情報をデータベースではなく、Cookie のみで管理していました。

ユーザーは多少の知識を持っており、自身でブラウザの Cookie 設定を確認したが、Cookie が自動で削除される設定にはなっておらず、ブロックもしていないという情報が明らかとなりました。デバイスやブラウザも同一であり、「お気に入り」が消えていたことを確認したのは、登録してから数日後とのことでした。

以上の状況から、コードに問題がありそうだと判断し、調査を行いました。

原因

結論から言うと、「お気に入り」の Cookie データ登録時に期限設定をしていなかったため、セッションクッキーとして登録され、ブラウザアプリを閉じたタイミングで該当のクッキーが削除されていた ことが原因でした。これは PHP, JavaScript のいずれにおいても発生する問題です。

「セッションクッキー」とは

セッションクッキーとは、ユーザーがブラウザを閉じるまでの間だけ有効なクッキーのことです。クッキーを発行する際に有効期限を指定しなかった場合、自動的にセッションクッキーとして扱われます。

セッションクッキーは、一時的なデータ保存には便利ですが、長期間のデータ保持には適していません。そのため、ブラウザを閉じるとクッキーが削除され、再度同じサイトにアクセスした際には保存されていた情報が失われてしまいます。

下記は Edge ブラウザの開発者ツール「アプリケーション」からクッキーを確認した時のスクショです。期限の表示が「セッション」になっていることが分かります。

セッションクッキー

$expires = time() + (365 * 24 * 60 * 60);  // 365日 = 1年
$cookieName = 'test_cookie';
$cookieContent = 'test_cookie_name';
$domainName = 'example.com';
$secure = true;
$sameSite = 'Lax';
setcookie($cookieName, $cookieContent, $expires, '/', $domainName, $secure, true, $sameSite);

参考: https://www.php.net/manual/ja/function.setcookie.php

const expires = new Date();
expires.setTime(expires.getTime() + (365 * 24 * 60 * 60 * 1000));  // 365日 = 1年
const cookieName = 'test_cookie';
const cookieContent = 'test_cookie_content';
const domainName = 'example.com';
const secure = 'Secure';
const sameSite = 'Lax';
document.cookie = `${cookieName}=${cookieContent}; domain=${domainName}; path=/; expires=${expires.toUTCString()}; ${secure}; SameSite=${sameSite}`;

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

補足情報

  • Secure 属性: Secure 属性を指定することで、クッキーは HTTPS 通信でのみ送信されます。セキュリティを強化するために、可能な限り設定することを推奨します。ただし、HTTPS でない場合は、この属性を設定しないように注意が必要です。
  • SameSite 属性: SameSite 属性を指定することで、クッキーがクロスサイトリクエストで送信されるかどうかを制御できます。SameSite=Lax を指定すると、クロスサイトの状況でのクッキー送信が制限され、CSRF 攻撃に対する防御が強化されます。より厳格な制限が必要な場合は SameSite=Strict を検討してください。