とある CakePHP2 で作られたシステムで不定期にセッションが切れてしまうという現象があったのですが、その原因が判明したので書き記しておきます。必ずこれがセッション切れの原因というわけではなく、あくまでも一つのケースです。
結論から書きますと、CakePHP2 の checkAgent という機能と、ブラウザのラピッドリリースの相性の悪さが原因となります。
CakePHP 2.X Cookbook - セッション#セッションの設定 に
Session.checkAgent - ユーザーエージェントはチェックされるべきです。 ユーザーエージェントがセッションとマッチしない場合、そのセッションは破棄されます。
とあります。checkAgent 機能ではセッションキーとともにブラウザの UserAgent も照合され、合致しない場合はセッションを継続できません。そして checkAgent 機能はデフォルトでは有効になっています。
checkAgent 機能は、攻撃者がセッションキーを奪取してなりすましアクセスをしようとしても UserAgent を再現できなかった場合には不正アクセスを防ぐことができるというものです。セキュリティ的には有益な機能ですが、問題は UserAgent の不変性です。
昨今の多くのブラウザはラピッドリリースを採用していますし、リリースの反映も自動的に行われるようになっています。早ければ数日程度の短期間に、ユーザが気付かない内にブラウザのバージョンアップが行われています。そして、UserAgent にはブラウザの詳細なバージョン情報も格納されています。例えば現在私が使っているブラウザの UserAgent は Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
です。80.0.3987.149
という詳細なバージョン情報が入ってますね。おそらく数日後にはここは変化していることでしょう。UserAgent が変わってしまうと、CakePHP2 は同一ユーザではないと認識し、セッションが破棄されます。
セッションタイムアウトを1日以内程度の短い時間に設定している場合は checkAgent 機能を有効にしても問題ないですが、何日にも渡ってセッションを有効にしたい場合には不適です。そして今回のシステムもセッションタイムアウトを長期間に設定していました。
checkAgent 機能はセキュリティ的には有益な機能ですが、現在のブラウザリリース事情には残念ながら合っていません。実際、CakePHP3 ではこの機能は削除されています。
checkAgent 機能はデフォルトで有効になっているため、無効にするには app/Config/core.php
を以下のように書き換えます。
--- a/app/Config/core.php
+++ b/app/Config/core.php
@@ -227,7 +227,8 @@
* the cake shell command: cake schema create Sessions
*/
Configure::write('Session', array(
- 'defaults' => 'php'
+ 'defaults' => 'php',
+ 'checkAgent' => false
));
/**