導入
このブログのキャッチコピーは「未来の自分のための技術メモ、時々あなたのためのヒント。」ですが、今回は過去の自分が格闘したデバッグの記録が、今まさに同じ問題で悩んでいるあなたの「ヒント」になるかもしれません。
エンジニアなら誰しも、「どう考えても説明がつかない…」という奇怪なバグに遭遇した経験があるかと思います。
今回は、古いバージョンのPHPフレームワーク「CakePHP 1.3」で、http
とhttps
が混在するサイトを構築した際に直面した、そんな不思議な「セッション切れ」問題の調査から解決までの一部始終を、探偵物語のようにお届けします。
事件の概要:消えるセッションCookie
まずは、事件の概要です。
ECサイトの一部ページのみを非SSL(http)にする必要があり、https-とhttpをページごとに行き来するサイトを構築していました。すると、以下のような奇妙な現象が発生しました。
https
のログインページからログインhttps
の会員ページに遷移(ここまではOK)http
の一般ページに移動- 突然ログアウト状態になり、ログインページに強制送還される
ブラウザの開発者ツールで調査すると、https
からhttp
へ移る瞬間に、セッションを維持するためのCookieがきれいに消え去っていることが判明しました。これが事件の第一発見です。
第一の容疑者:session.cookie_secure
http
とhttpss
をまたいでCookieを共有するには、PHPの設定session.cookie_secure
がfalse
(無効)になっている必要があります。この設定がtrue
だと、Cookieはhttps
通信でしか送られなくなり、http
のページでは使えません。
「原因はこれに違いない!」と確信した私は、CakePHPの設定ファイルapp/config/core.php
に、この設定を強制的にfalse
にする記述を追加しました。
Configure::write('Session', array(
'ini' => array(
'session.cookie_secure' => false,
)
));
これで解決するはずでした。しかし…症状は全く改善しませんでした。
設定ファイルで書いたはずの指示が、なぜか無視されているのです。
真犯人を追え!フレームワークの深層へ
設定が効かない以上、容疑者はCakePHPの内部にいると判断。私はフレームワークのコアファイル、cake/libs/cake_session.php
に足を踏み入れました。
そして、ついに「犯行現場」を発見したのです。
// ...
$iniSet = function_exists('ini_set');
if ($iniSet && env('HTTPS')) {
ini_set('session.cookie_secure', 1); // ← コイツが犯人だ!
}
// ...
これは衝撃的な事実でした。CakePHP 1.3は、https
でのアクセスを検知するたびに、開発者の設定をすべて無視して、問答無用でsession.cookie_secure
を有効にしていたのです。これでは、設定ファイルでいくらfalse
と叫んでも、声は届きません。
事件解決、そして得られた教訓
原因が特定できれば、解決は目前です。この強制設定を無効化することで、セッションは無事に維持されるようになりました。(ちなみに、このおせっかいな挙動は、CakePHP2以降ではちゃんと修正されています。)
この事件から得られた教訓は、
- フレームワークを盲信するな: 便利さの裏には、時として予期せぬ「仕様」が隠れている。
- 設定が効かない時は、ソースコードを読め: 結局、最も信頼できるドキュメントはソースコードそのものである。
- 古いシステムには、歴史的な経緯が眠っている: なぜこのような実装になったのか、その背景を想像するのもまた一興。
まとめ
今回は、古いCakePHPで発生した不思議なセッション切れ問題のデバッグ記録をご紹介しました。
一見すると不可解なバグも、地道に証拠(ログ)を集め、容疑者(コード)を追い詰めていけば、必ず真相にたどり着けます。
この記事が、今まさに困難なデバッグに直面しているあなたの、問題解決の「ヒント」になれば幸いです。
コメント