2005年12月 7日
PHPでセッション重複 >>Perl
この辺とか
この辺とか
で、PHP のセッション関連に触れてたわけですが、触ってた時に、こりゃぁ重複するなあ。。という感じでしたが、やっぱり重複するようです。
ネタにしてませんでしたけど。
(以下4.0.6でのソース。最新も多分そんなに変わらない)
session.c
gettimeofday(&tv, NULL);
PHP_MD5Init(&context);
sprintf(buf, "%ld%ld%0.8f", tv.tv_sec, tv.tv_usec, php_combined_lcg() * 10);
PHP_MD5Update(&context, buf, strlen(buf));
ext/standard/log.c
/*
* combinedLCG() returns a pseudo random number in the range of (0,1).
* The function combines two CGs with periods of
* 2^31 - 85 and 2^31 - 249. The period of this function
* is equal to the product of both primes.
*/
#define MODMULT(a,b,c,m,s) q = s/a;s=b*(s-a*q)-c*q;if(s<0)s+=m
double php_combined_lcg(void)
{
long q;
long z;
LCGLS_FETCH();
MODMULT(53668,40014,12211,2147483563L, LCG(s1));
MODMULT(52774,40692,3791, 2147483399L, LCG(s2));
z = LCG(s1) - LCG(s2);
if(z < 1) {
z += 2147483562;
}
return z * 4.656613e-10;
}
Cは必要に駆られないとやらないというか基本的に逃げの姿勢ですので、斜め読みしかしてません、悪しからず。
で、ロジック的に考えてみましょう。
「ランダム値は完全なランダム値にはなり得ない」ので、ミリ秒を取得した上でのランダムだから「重複しない」ということは有り得ません。
重複する可能性は低い、とは言っても重複する可能性はゼロでは無い。
ランダムだから重複しないんじゃ?という問いがあれば、ランダムだからランダム的にぶつかるのです、はい。絶対にぶつからないなら、それは固有値。
セッションとして固有なキーを渡す必要があるのなら、「本当に固有で重複しえないキーを生成」しなければなりません。
「idを生成した時点」で排他セッションファイルを生成し、ロックが完了するまで待つ、出来なければ排他ロックに失敗したということで、idを作成し直す、というロジックであれば、ユーザが待たされる時間が長くなる場合もありますが、ほぼ重複はしないでしょう。・・・というような冗長なセッション処理をお客用プログラムでは自分で書いています。(Perlでの話しですけどね)クラスタ環境ではまずいので、その場合はその処理を入れなければなりませんけど。
当該PHPのセッションID生成部ではflockはここではしていないように見えます。IDが重複してないと判断するが、最終的には(ファイル書き出しとCOOKIE格納時)重複する、というロジックになると思います。
アクセス数が多いサイトで発生する確率が上がるでしょう。そして、確率が上がるということは、不具合が発生する率も高まるということを意味します。
どこまで重複する可能性があっても良いか、というところにかかってくるのでしょうが。
www.pot.jpさんにも、セッション重複問題が書かれています。
きちんと理解していないAPIやモジュールをむやみに信用して作成するのはリスクが高いのです。
自分で書いてもリスクは同じといえば同じですが。
セッションとは、ユーザが操作したショッピングカーとの内容等を一時的に格納するために、COOKIEをブラウザに格納した上で、サーバ上にセッション情報を保存しておく、というものです。
ブラウザのCOOKIEに格納したIDから、一時的に保存したカートの中身を表示させたり、商品を追加したり、といった処理を行うのが一般的です。
ですから、重複するセッション情報があった場合、他のユーザと重複してしまうため、まずいのです。
トラックバック
現在、この記事はトラックバックを受け付けておりません。
コメント
現在、この記事はコメントを受け付けておりません。