概要
ロードバランサー(以下LB)でHTTPS終端 → HTTP転送の構成において、古いPHPシステムでCookieが保存されないという現象が発生。
Laravelでは問題なし。だが、生PHPで書かれた管理画面はログイン成功しても、すぐクッキーが消えてログインループに。
構成概要
- LB(HTTPS)→ Node01(HTTP)
- クライアントの接続先は
https://admin.exmple.com/
- Node側は80番で待ち受け
- Laravelは
TrustProxies
にてX-Forwarded-Proto
を信用 - 生PHPの管理画面は10年以上前に作成された古いコード
発生した問題
✅ ログイン処理成功
→ `setcookie()` 実行
→ 開発者ツールで一瞬クッキーが確認できる
→ すぐにクッキーが消える(1秒以内)
→ クッキーが無いため再ログインループに突入
Nodeのログの様子:
[02/Apr/2025:16:26:16 +0900] "GET / HTTP/1.0" 200 ...
→ クッキーが残らず、ログイン直後にトップページへ302リダイレクト → 再びログイン画面に戻される
⸻
原因
✅ setcookie() で ドメイン指定していなかった
// NG:省略するとクッキーが "admin.example.com" 扱いになりがち
setcookie("ADMINUSER", $user_id, 0, "/");
この状態で LB + HTTPS + HTTP転送 + 302リダイレクト が挟まることで…
• ブラウザがクッキーのスコープを「不明確なドメイン」扱いにしてしまう
• secure=false でも、対象ドメインがはっきりしていないため、ブラウザがクッキーを送らなくなる or 破棄
✅ LBを超えているが、リクエストURLはずっと https://admin.exmple.com/
→ 表面上は同一ドメインに見えるが、サーバサイドとブラウザの認識にズレがある
⸻
対処法(生PHP)
setcookie() に明示的に ドメイン指定 を加える!
setcookie(
'ADMINUSER',
$user_id,
[
'expires' => time() + 3600,
'path' => '/',
'domain' => '.exmple.com', // ← これが超重要!!
'secure' => true, // HTTPSの時はtrueに
'httponly' => true,
'samesite' => 'Lax'
]
);
→ これでブラウザが「おっ、これは .exmple.com ドメインのやつやな!」と安心してクッキーを保持する。
なぜLaravelでは問題なかった?
• Laravelは TrustProxies を使って X-Forwarded-Proto や Host を信用
• setcookie() 相当の処理も、ヘッダの内容から判断して domain と secure を適切にセットしてくれている
⸻
教訓
• LB越しの構成では、ドメインとプロトコルに超敏感な挙動が起こりうる
• 生PHPや古いコードでは、setcookie()のパラメータを明示しないと事故る
• LaravelやモダンなFWはうまく吸収してくれてるが、古い資産を載せ替える時は特に注意!
⸻
まとめ
• 同じドメイン内のリダイレクトでも、クッキーが「別物扱い」されるケースはある
• LB構成 + 古いPHP + setcookie未指定 → 地雷原
• ブラウザが「このクッキー送っていいのか?」って戸惑う時点で負け
⸻
再発防止メモ
• LB配下では domain・secure の指定はセットで!
• PHP 7.3以降は配列形式でわかりやすく書ける
• 生PHPを保守してる場合、古いコードでも「今の通信環境」で再検証するべし!