在客戶端登錄網站時,被訪問的PHP頁面可以使用session_start()打開session,這樣就會產生客戶端的唯一標識session id(可以通過session_id()獲取/設置)。Session id可以通過兩種方式保留在客戶端。一種是自動加入到get的url中,或者POST的表單中,默認情況下變量名爲PHPSESSID;另一種是通過COOKIE,,默認情況下,這個COOKIE的名字爲PHPSESSID.
多服務器共享session
必須實現兩個目標:一個是各個服務器對同一個客戶端產生的session id必須相同,並且可通過同一個cookie進行傳遞,也就是說各個服務器必須可以讀取同一個名爲PHPSESSID的COOKIE;另一個是session數據的存儲方式/位置必須保證各個服務器都能夠訪問到,簡單地說就是多服務器共享客戶端的session id,同時還必須共享服務器端的session數據。
實現方案
首先創建數據庫表
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')
)type=MyISAM;
sesskey爲SESSION ID,expiry爲session過期時間,data用於保存session數據
默認情況下session數據是以文件方式保存,想要使用數據庫方式保存,就必須重定義SESSION各個操作的處理函數。Php提供了session_set_save_handle()函數,可以用此函數自定義session處理過程,首先要先將session.save_handler改成user.在php中進行設置
Session_module_name('user')
Session_module_name()見幫助文檔
面向對象的代碼:
<?php
define('MY_SESS_TIME',3600);//SESSION生存時間
//類定義
Class My_Sess
{
function init()
{
$domain = '.inform.com';
ini_set("session.use_trans_sid",0);//不使用get/post變量方式
ini_set('session.gc_maxlifetime',MY_SESS_TIEME);//session生存時間
ini_set("session.user_cookies",1);//使用cookie保存session id的方式
ini_set("session.cookie_path","/");
ini_set("session.cookie_domain",$domian);//多主機共享保存session id的cookie
session_module_name('user');//將session.save_handler設置爲user,默認爲files
session_set_save_handler(//定義session各項操作所對應的方法名
array("My_Sess","open"),//對應於靜態方法My_Sess::open()下同
array("My_Sess","close"),
array("My_Sess","read"),
array("My_Sess","write"),
array("My_Sess","destroy"),
array("My_Sess","gc"),
);
}
function open($save_path,$session_name)
{
return true;
}
function close()
{
global $MY_SESS_CONN;
if($MY_SESS_CONN)
{
$MY_SESS_CONN->Close();//關閉數據連接
}
return true;
}
funcion read($sesskey)
{
global $MY_SESS_CONN;
$sql = "select data from sess where sesskey=".$MY_SESS_CONN->qstr($sesskey)." and expiry>=".time();
$rs = &$MY_SESS_CONN->Execute($sql);
if($rs)
{
return '';
}
else
{
$v =$rs->fields[0];
$rs->close();
return $v;
}
return '';
}
function write($sesskey,$data)
{
global $MY_SESS_CONN;
$qkey = $MY_SESS_CONN->qstr($sesskey);
$expiry = time() + My_SESS_TIME;//設置過期時間
$arr = array(//寫入session
"sesskey" => $qkey,
"expiry" => $expiry,
"data" => $data);
$MY_SESS_CONN->Replace("sess", $arr, "sesskey", $autoQuote = true);
return true;
}
function destroy($sesskey) {
global $MY_SESS_CONN;
$sql = "DELETE FROM sess WHERE sesskey=".$MY_SESS_CONN->qstr($sesskey);
$rs =& $MY_SESS_CONN->Execute($sql);
return true;
}
function gc($maxlifetime = null) {
global $MY_SESS_CONN;
$sql = "DELETE FROM sess WHERE expiry<".time();
$MY_SESS_CONN->Execute($sql); //由於經常性的對錶 sess 做刪除操作,容易產生碎片
$sql = "OPTIMIZE TABLE sess"; //所以在垃圾回收中對該表進行優化操作。
$MY_SESS_CONN->Execute($sql);
return true;
}
}
/使用 ADOdb 作爲數據庫抽象層。
require_once("adodb/adodb.inc.php");
//數據庫配置項,可放入配置文件中(如:config.inc.php)。
$db_type = "mysql";
$db_host = "192.168.212.1";
$db_user = "sess_user";
$db_pass = "sess_pass";
$db_name = "sess_db";
//創建數據庫連接,這是一個全局變量。
$GLOBALS["MY_SESS_CONN"] =& ADONewConnection($db_type);
$GLOBALS["MY_SESS_CONN"]->Connect( $db_host, $db_user, $db_pass, $db_name);
//初始化 SESSION 設置,必須在 session_start() 之前運行!!
My_Sess::init();
?>