多子域/多伺服器架構下,用戶在 A 系統登入後跳轉到 B 系統需重新登入。核心原因:各伺服器獨立產生 Session ID、Session 檔案分散在本地檔案系統。
.example.com),所有子域自動攜帶同一 PHPSESSID。
CREATE TABLE `sess` (
`sesskey` VARCHAR(32) NOT NULL DEFAULT '',
`expiry` BIGINT(20) NOT NULL DEFAULT '0',
`data` LONGTEXT NOT NULL,
PRIMARY KEY (`sesskey`),
KEY `expiry` (`expiry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
使用 session_set_save_handler() 覆寫六個回調:open, close, read, write, destroy, gc。
close();
return true;
}
static function read($sesskey) {
$sql = "SELECT `data` FROM `sess` WHERE `sesskey`=" . self::$db->qstr($sesskey) . " AND `expiry`>=" . time();
$rs = self::$db->execute($sql);
if ($rs && !$rs->EOF) {
$v = $rs->fields[0];
$rs->close();
return $v;
}
return '';
}
static function write($sesskey, $data) {
$arr = array(
'sesskey' => $sesskey,
'expiry' => time() + MY_SESS_TIME,
'data' => $data
);
self::$db->replace('sess', $arr, 'sesskey', true); // ADODB REPLACE
return true;
}
static function destroy($sesskey) {
$sql = "DELETE FROM `sess` WHERE `sesskey`=" . self::$db->qstr($sesskey);
self::$db->execute($sql);
return true;
}
static function gc($maxlifetime = null) {
$sql = "DELETE FROM `sess` WHERE `expiry`<" . time();
self::$db->execute($sql);
// 定期整理碎片
self::$db->execute("OPTIMIZE TABLE `sess`");
return true;
}
}
// 使用範例 (需 ADODB)
require_once('adodb/adodb.inc.php');
$db = ADONewConnection('mysqli');
$db->connect('127.0.0.1', 'root', 'pass', 'sess_db');
$sess = new My_Sess($db);
$sess->init();
$_SESSION['user'] = 'admin';
print_r($_SESSION);
?>