Security.levelはどこへ消えた?(CakePHP2系の話)

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
チーズはどこへ消えたー?

おまとめ三行

以前はcore.phpにSecurity.leveってのがあったのに
気がついたらそれが見当たらなくなっていた
CakePHP2系でセッション時間を設定するには?

CakePHP1.3でログイン画面を実装した際、そのセッション時間というかログインが切れるまでの時間って、core.phpっていうファイルの中にある以下の項目で設定してました。

Configure::write('Session.timeout', '1500');
Configure::write('Security.level', 'low');

『Seculity.level』ってのは『high』『medium』『low』の三つが指定できて、それに応じた秒数がセッション時間になってました。上記の場合だと、Session.timeoutが1500でSecurity.levelがlowなので、1500×300で45000秒ってことになりますかね。だいたい半日くらい。highだと×10秒でmediumだと×100秒になります。

ほんでまあ、このSecurity.levelってやつがなかなか曲者でして、セキュリティのことを考えるとhighにするのが良いとか何とか言いつつ、highにするとあまりよろしくない挙動をするとか何とかで、結局mediumにするのが良いだのlowまで下げちゃった方が良いだのって話になることが多く……僕も仕事で1.3を使ってるところがあるんですが、lowに設定しております。lowだとセッションIDを新しく書き直さない的な問題があるんですが、それはコンポーネントのauth.phpをちょちょいと書き直すだけで何とかなるから、僕もそれで対応してます。

前にもちょこーっとそこら辺のことについて書いたことがあるんだけどね。もし何かの足しになれば。

Security.levelがlowでも慎重を期してセッションIDくらいは新調しとく?



まあ1.3のことはともかくとして、今日は、2.3にしたらこのSecurity.levelってのが見当たらなくなったんで、それについてちょっと調べてみたことをご報告させていただきたく思いまして。ついでに、2.0の話もちょっと聞いてもらおうと思いまして。

検証しきれてない部分もあるから、少しだけ妄想が入りますが、その辺はなあなあでお願いしますm(_ _)m

あと妄想が入るとはいえ、一応開発に関する記事だから、カテゴリは開発技術にするけど、その辺もなあなあでお願いしますm(_ _)m



そこにいるだけっぽい

CakePHP2.0になっても、このSecurity.levelってのは存在するんだけど、タイムアウトの時間にはあまり関係がなくなったような気がします。ちゃんと検証したわけじゃないんでもしかしたら間違ってるかもだけど、一応残ってるってだけで、実際に機能してんのかどうかもよく分かんねえ。

1.3の頃は、コアの方にあるcake_session.phpのところで、セッション時間を設定する際に、このSecurity.levelの設定が使われてるんですけど、2.0になって、同じことをやってるCakeSession.phpってファイルを見てみると、セッション時間の設定に、これが特に使われてるように見えないんすよ。

ここだけ書いても分かり辛いと思うけど、一応載せとくと……。

//CakePHP1.3のcake_session.php
$this->sessionTime = $this->time + (Security::inactiveMins() * Configure::read('Session.timeout'));

//CakePHP2.0のCakeSession.php
self::$sessionTime = self::$time + ($sessionConfig['timeout'] * 60);

1.3の方に『Security::inactiveMins()』ってのがあるじゃん? これが、Security.levelに応じた値を返す関数なんすよ。highだったら10とか、lowだったら300とか。

このSecurity::inactiveMins()自体は2.0にもあって、同じようにSecurity.levelに応じた数字を返すようにはなってんだけど、でも使ってなさそうなのよね。

だから、これは僕の出した結論だけど、2.0の場合、Security.levelは何でも良いんじゃね? と思うんですよね。

いや、まあ、セキュリティのもっと深いとこまで入って行くと、これが影響してくんのかもしれないけど、少なくともセッション時間、ログイン時間に関する部分では、これは何でも良いような気がする。



改めましてセッション時間の方を

2.0になってからは、Session.timeoutの方もちょっと書き方が変わっておりまして……デフォルトだと、core.phpの中のSessionに関する記述は、こんな風になってる。

Configure::write('Session', array(
  'defaults' => 'php',
));

『defaults』っていう項目は、どの設定に従うかみたいな設定項目で、『php』にしとくと、php.iniのセッションの設定に従うっぽいです。他には『cake』『cache』『detabese』が設定できるみたいで、それぞれどんな設定に従うのかは、CakeSession.phpの中の『_defaultConfig()』って関数を見れば分かります。

ちなみにCakeSession.phpは『Model/Datasource』ってとこに入ってる。

じゃあ、タイムアウトの時間はどうやって書くのかってーと……

Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1500,
));

こんな風に書くようです。

1.3と大きくは変わらない……と思いきや、1.3のときは秒だったのが、2.0だと分になってるようです。つまりこれは、1500秒じゃなくて、1500分。一日ちょいですね。

初期設定ではこれが省略されてますが、省略されてる場合は_defaultConfig()の中の設定が適用されます。上記みたく『’defaults’ => ‘php’』って書いてる場合、初期設定ではtimeoutは240ってなってるので……4時間ですね。つまり何も設定しなければ、4時間でログインが切れることになる。



なんでそーなるのっ!?

そーゆーことなら、例えば『’timeout’ => 1440』って書いとけば、一日くらいログイン状態が持続するわけだね! かーんたーん! 1.3の頃より直感的に分かりやすいぜ!!

……って思ったそこの君ぃ!

まあ、そりゃそう思うわな。俺だってそう思ったさ。

でも、話はそう簡単でもないらしい。何でこんなややこしいことになってんのかよく分かんないけど、そういう風になってるんだから仕方ないよね。

ここでもう一度_defaultConfig()を見ると、timeoutの他に『cookieTimeout』っていう項目もあんのね。timeoutと同じく、240って数字がセットされてる。

どうやら、このcookieTimeoutがtimeoutよりも少ない数字の場合、ログイン時間はcookieTimeoutの方に従うみたいなの。

えーっと……文だけだとあれか。いくつかパターンを書いてみるかいね。

//パターン1
Configure::write('Session', array(
  'defaults' => 'php',
));

//パターン2
Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1440,
));

//パターン3
Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 10,
));

//パターン4
Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1440,
  'cookieTimeout' => 10,
));

パターン1は設定を省略した場合。デフォの場合っすね。事実上、これは『’timeout’ => 240, ‘cookieTimeout’ => 240』と同じだね。この場合は、さっきも書いたけど、240分、4時間でログインが切れる。

パターン2は、timeoutを1440分(ちょうど一日)にしたパターン。cookieTimeoutは省略してるんで、Cake側の設定で240が入る。この場合は、やっぱり4時間でログインが切れちゃう。

パターン3は、timeoutを10分にした場合。cookieTimeoutは変わらず240分なんだけど、この場合は10分でログインが切れる。

パターン4は、timeoutを1440分にして、cookieTimeoutを10分にした場合。この場合は10分でログインが切れる。

まあ一言で言うと、timeoutとcookieTimeoutの数字が少ない方の時間が適用されるって感じかなぁ。何でそうなるかってーと、セッションのタイムアウトの時間をめーいっぱい大きくしたとしても、そのセッションを管理しているクッキーの方が先にタイムアウトになっちゃうと、結局セッションが破棄されちゃう……っていう考え方になるのかしらね。cookieTimeoutは、変数名のごとくクッキーの方のタイムアウト時間を設定しているらしいんで。



ってことで、ログインが次の日まで切れないようにしたい場合は、上のどのパターンでもダメってことですね。

timeoutとcookieTimeoutを両方1440にしないといけない。

Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1440,
  'cookieTimeout' => 1440,
));



ちょびっとだけ蛇足的な

一応これでセッション時間の設定はできたってことで良いんですけど……場合によっては、ガベージコレクションってのが影響してくることがある。

僕も詳しくはないんですが、以前、僕なりに調べたことを書いたことがあるんで、これも参考になれば。結構昔の記事だから、仕様が変わったりしてるかな……?

ゴミ収集車にはめられた

ざっくり言うと、PHPの設定で『session.gc_maxlifetime』っていうのがあって、これが短いと、セッションやクッキーのタイムアウトを長くしといても、破棄されてしまうことがある。

これはCakePHPじゃなくてPHPの設定だから、ini_set()で設定することもできるんだけど、CakePHPの場合は、core.phpの方で書くこともできる。

Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1440,//分
  'cookieTimeout' => 1440,//分
  'ini' => array('session.gc_maxlifetime' => 86400),//秒
));

これもちょいややこしいんだが、session.gc_maxlifetimeは秒で設定します。



時代はめまぐるしく変わる

さあ、まだ話は終わりじゃないぜい。今度は2.3の話。

2.0のときはここまで書いてきたような感じなんだけど、ついこの前、CakePHPのバージョンを2.3にアップしてみたら、さらに状況が変わってた。具体的にいつからこうなったのかは分からないけど、少なくとも2.3ではこうなってた。

まず、core.phpからSecurity.levelがなくなってた。

例の『Security::inactiveMins()』は残ってるんだけど、でもやっぱり、パッと見た感じでは、あるだけで使われてないように見えるかなぁ。

まあそこは2.0のときと特に変わらないんだけど、ここでもう一つ。

『_defaultConfig()』を見ると、cookieTimeoutの初期設定がなくなってた。timeoutの方は変わらず240分っていう初期設定がある。

ってことは、2.3の方は、こう書いとけばログイン時間を一日に設定できるってことですね。

Configure::write('Session', array(
  'defaults' => 'php',
  'timeout' => 1440,
));

cookieTimeoutの方は、設定を省略すると、timeoutで設定した数字を入れるようになってるから、こう書けばcookieTimeoutも自動的に1440分になる。

実はこの、cookieTimeoutを省略した場合はtimeoutで設定した数字を入れるっていう処理自体は、2.0のときもCakeSession.phpの中でやってるんですけどね。ただ、CakeSession.phpの中で、cookieTimeoutが省略されるっていう事態が発生しないようになってたからね。デフォルトの値を自動的にセットしちゃってたから。

具体的にいうと、2.0でも2.3でも、CakeSession.phpの中にこういうコードがあんの。

if (isset($sessionConfig['timeout']) && !isset($sessionConfig['cookieTimeout'])) {
  $sessionConfig['cookieTimeout'] = $sessionConfig['timeout'];
}

でも2.0のときは、『isset($sessionConfig[‘cookieTimeout’])』で必ずtrueが返ってくる設定になっちゃってたってことだね。

たぶん開発が進む中で「ここ、絶対にtrue返って来ちゃうね? 修正しようぜ!」的なことがあったんだと思う。

ちなみに2.3の場合は、記述を省略した場合、session.gc_maxlifetimeもtimeoutで設定した値を入れるようになってる。

ユーザーの設定がなるべく楽になるよう、バージョンアップを重ねるごとにちゃくちゃくと進化しているみたいですね。

良い仕事してますねー、CakePHPさん。






ってなわけで、1.3 → 2.0 → 2.3という時代の移り変わりに伴うSecurity.levelの話でした。いや、ほとんどセッション時間に関する話だったか。

とにかく、最初は絶対に必要な設定だったはずのSecurity.levelが、気づいたらいなくなってたっつー話っすわ。一軍にいたあいつが、いつの間にかベンチ入りすらできずに二軍に落ち、人知れず引退してた感じだね。そう考えると、ちょっとだけ寂しいことなのかもしれないね。

ま、今日の結論としては、秒と分にだけ気をつけとけば、セッション時間は簡単に設定できるようになった……ってことで、良いかしらね。

CakePHP2.x セッションタイムアウト設定 | 作業メモ 2014年04月13日 17:48:48
[…] 参考ありがとう: http://wataame.sumomo.ne.jp/archives/3983 http://norm-nois.com/blog/archives/2290 […]
もしかしたら何か関連しているかも?