複数Webサーバ、単一セッション管理でセッションかぶっちゃう問題ですが、調べたら5人日ぐらいかかりそう・・・とか思ってましたが、この間の勉強会で聞いたら、
「session_id()でセッションID設定できる。」
一瞬で解決しました。
解決策をまとめると、
「セッション維持してくれるロードバランサーを使う」 OR 「セッションIDにアドレスをくっ付ける」
となりました。
実装はこんな感じか!?
session_id(str_replace(".", "a", $_SERVER["SERVER_ADDR"]).session_id());
Mojavi2で使うためにIPでユニークなセッションIDを使うコンテナ、IpUniqueSessionContainerを作ってみました。
<?php
require_once (USER_DIR."SessionContainer.class.php");
class IpUniqueSessionContainer extends SessionContainer {
function load(& $authenticated, & $attributes, & $secure) {
if (ini_get("session.auto_start") != 1) session_start();
session_id(str_replace(".", "a", $_SERVER["SERVER_ADDR"]).session_id());
if (!isset($_SESSION["attributes"])) {
$authenticated = false;
$attributes = array();
$secure = array();
} else {
$authenticated = $_SESSION["authenticated"];
$attributes = $_SESSION["attributes"];
$secure = $_SESSION["secure"];
}
$_SESSION["authenticated"] =& $authenticated;
$_SESSION["attributes"] =& $attributes;
$_SESSION["secure"] =& $secure;
}
}
?>
IpUniqueSessionContainer-0.1.zip
index.phpのUSER CONTAINER SETTINGSのところでこんな感じで使う。
require_once(BASE_DIR."opt/user/IpUniqueSessionContainer.class.php");
$user =& $controller->getUser();
$user->setContainer(new IpUniqueSessionContainer());
ref: PHPのセッションID2
Trackback URL:
http://p0t.jp/cgi-bin/mt/mt-tb.cgi/688
Listed below are links to weblogs that reference PHPのセッションID3:
» [PHP]UNIQUEなSessioIDを振る
from MugeSoの日記
[http://p0t.jp/mt/archives/2005/07/web_4.html:title=複数Webサーバ、単一セッション管理でセッションかぶっち...
[Read More]
Comments
ちょっと実験したところ、
session_start()の前にsession_id()で設定しないと設定したsession_idは有効になりませんでした。
その上、session_start()前だとsession_id()は空です。
しかも、session_start()の前にsession_id()で設定すると毎回違うセッションIDがふられる。
また、UNIQUEなIDの振出については$_SERVER['UNIQUE_ID']を用いると言う提案。
http://httpd.apache.org/docs-2.0/ja/mod/mod_unique_id.html
によると、UNIQUE_IDは時刻が正確である限り、真にUNIQUEであるとのこと。
同じ生成方法を取ればapacheでなくてもUNIQUEな値を得ることができる(とおもう)ので、apacheでなければそれを用いる。
まとめると
if(session_id()=='') {
$Sid = ini_get('session.use_only_cookies') ? '_COOKIE' : '_REQUEST';
if (!isset(${$Sid}[session_name()]))
{
session_id($_SERVER['UNIQUE_ID']);
}
session_start();
} else {
// 既にセッション開始していた時の対応
}
長文失礼しました。 早くblog始めよう。。。
一度session_id()を取得するんじゃなくて、
session_id(md5($_SERVER["SERVER_ADDR"].uniqid(rand(),1)));
とかやるのはどうですか?
某所でこんなコードを書いたことがあって、正解かどうか激しく気になります。正解でしょうか?教えてください。
あと、$_SERVERの値って、php.iniやらの設定で取れないことあるよね。そんな時どうしよう。どうしよう・・・