サーバー運用

PHPセッション問題を解決して認証を維持

2026-04-26 読了6分 8PV
PHPセッション問題を解決して認証を維持

こんにちは、AIシステムズです。
この記事は、代表コバが現場で対応してきたPHP・Webアプリ運用の知見をもとに、AIを活用して構成・執筆し、弊社にて最終チェックを行ったものです。

「ログインしたのに次のページで未ログイン扱いになる」「ショッピングカートの中身が突然消える」「ロードバランサ配下でセッションが維持されない」——PHPベースの業務システムやECサイトで頻発するトラブルです。セッションが維持されない原因は、Cookie・保存先・ロードバランサ・タイムアウトの4層に分けて考えると整理できます。

  • PHPセッションが切れる主要原因
  • セッションCookieとSameSite属性
  • セッションの保存先(ファイル・Redis・DB)
  • ロードバランサ配下での落とし穴
  • セキュリティ上やってはいけない設定

目次

  1. セッションが切れる典型パターン
  2. Cookieの設定を見直す
  3. セッション保存先の選定
  4. ロードバランサ配下での対応
  5. こういうサイトに向いている/向いていない
  6. 再発防止チェックリスト

セッションが切れる典型パターン

弊社が中小企業のPHPアプリで対応してきた中で、原因は次のいずれかです。

  • セッションCookieのSameSite/Secure設定が今のブラウザ仕様に合っていない
  • セッションのGC(gc_maxlifetime)が短く、すぐ消える
  • ロードバランサ配下で複数のPHPサーバーがあり、それぞれが別の場所にセッションを保存している
  • セッション保存先のディスクが満杯、またはsession.save_pathに書き込めない
  • サブドメイン・httpとhttpsの混在で、Cookieが別ドメイン扱いされている

Cookieの設定を見直す

SameSite属性

2020年以降のChromeでは、SameSite未指定のCookieはデフォルトで Lax 扱いになりました。クロスサイトの遷移(外部決済からの戻り、SAML認証からのリダイレクト)でセッションが切れる原因はこれであることが多いです。

session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'domain' => '.example.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',  // クロスサイトが必要なら'None'+secure
]);
session_start();

SameSite=None を使う場合は、必ずSecure属性とセットで指定します。Secureなしの None はブラウザに拒否されます。

ドメイン指定

サブドメイン間でセッションを共有するなら、domain.example.com のようにドット始まりで指定します。www.example.com 限定にすると、app.example.com へ遷移した時点でセッションが切れます。

セッション保存先の選定

  • files(デフォルト):単一サーバー構成なら問題なし。複数台で動かすと共有できない
  • Redis:複数台構成での標準。高速・スケーラブル
  • DB(MySQL等):既存DBインフラに乗せたい場合。Redisより遅いが運用が単純

Redisへの切り替え例:

// php.ini または ini_set
session.save_handler = redis
session.save_path = "tcp://redis-host:6379?database=0"

ロードバランサ配下での対応

複数のPHPサーバーが裏にいる構成では、セッションを必ず外部ストア(Redis等)に集約します。これをやらずに「スティッキーセッション(同じユーザーは同じサーバーに振り分け)」で逃げる構成は、サーバー1台が落ちたときにそのサーバーに紐付くユーザー全員のセッションが切れます。
さらに、ロードバランサ配下でHTTPS終端している場合、PHP側で$_SERVER['HTTPS']が空になります。secure属性のCookieを発行するには、次のような判定が必要です。

if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

セッションの寿命設定

セッションの寿命は2種類あります。

  • session.gc_maxlifetime:サーバー側でセッションデータを保持する秒数
  • session.cookie_lifetime:ブラウザ側でCookieを保持する秒数

両方を一致させないと、片方だけ生きていてもログインが続かない状態になります。たとえばカートの保持を24時間にしたいなら、両方を 86400 に設定します。

こういうサイトに向いている/向いていない

このセッション整備は、ログイン機能・カート・予約フォームを持つ中小企業のPHPベース業務システム・ECサイトに直接効きます。完全に静的な情報サイトには無関係です。

再発防止チェックリスト

  • SameSite属性を明示的に指定しているか
  • HTTPSサイトでSecure属性を付与しているか
  • 複数台構成なら外部セッションストアに集約しているか
  • セッションのgc_maxlifetime と cookie_lifetime が一致しているか
  • セッション保存先ディレクトリのディスク容量を監視しているか

まとめ

PHPセッションが切れる原因は、Cookie属性・保存先・ロードバランサ判定・寿命設定の4層に切り分けて対応します。SameSite明示、外部ストア化、X-Forwarded-Proto判定の3点を押さえれば、ほとんどのケースで安定します。

本記事は、代表コバが中小企業のPHPアプリ運用の現場で対応してきた知見をもとに、AIを活用して構成・執筆し、弊社にて最終確認を行っています。認証システムの設計、複数台構成への移行、セッション周りの問題切り分けについて、具体的な状況をふまえた相談を承っています。費用感だけ知りたい方も、お気軽にご相談ください。

AI Systemsへの無料相談はこちら

「何から始めればいいか分からない」段階からでも、お気軽にご相談ください。
まずは、お話を聞かせていただくだけでも大丈夫です。

無料で相談する
コバ

コバ

AI活用 / Web制作 / 業務自動化支援

中小企業さま向けに「お手頃に・早く・成果が出る」開発支援を行っています。AI・Web・自動化の3分野を、まとめてサポートしています。

この記事をシェアする

一覧へ戻る