session全教程(二)

二、php3,4中session的實現

在php3中是沒有session這種東東的,但我們又需要,怎麼辦呢?別急,有很多人替你做了這些,
這其中最有名的要算phplib了。你可以去國外下
載,也可以上國內大部分php站點下載。我們要做的第一件事是讓phplib和php3結合在一起使它能
工作。為了能實現這方面的弁遄A我們需要先安裝phplib。
跟著我來做,很容易的(以下方法在
win2000+php3.0.16+apache1.3.12+phplib7.2c+mysql3.23.21 for win32 上通過)
phplib最基本的弁鄍]括用戶認證,Session管理,權限及數據庫的抽像化。
怎樣使用phplib來實現session弁鄔O?
一、首先你將phplib解開,裡面有一個目錄叫"php",將這個目錄拷貝到apache的安裝目錄下。以
下以筆者的機器為例:
我的apache安裝在d:apache 目錄下,我將上面的"php"目錄拷貝到d:apache,並將phplib下的pages
目錄下的文件和目錄一起拷貝到
d:apachehtdocs下,注意不帶目錄本身。
phplib的類庫需要根據系統進行初始化,你可以修改local.inc文件,其中包含著一些基本參數,
你可以根據自己機器的實際情況來進行修改。
將d:apachephpprepend.php3文件中的一段程序改為如下樣子:

CODE
if (!isset( $_PHPLIB) or !is_array( $_PHPLIB)) {
$_PHPLIB["libdir"] = "d:/apache/php/"; //這兒改為你放phplib下php目錄的路徑
}

然後將d:apachephplocal.inc文件改如下:

CODE
class DB_Example extends DB_Sql {
var $Host = "localhost";//你的mysql數據庫所在主機名
var $Database = "test";//數據庫名
var $User = "root";//數據庫用戶名
var $Password = "";//數據庫用戶口令
}

最後一步執行解開的phplib目錄中的stuff目錄下的create_database.mysql文件,生成初始表。
我們說明一下phplib的工作原理,每一個使用phplib的頁面首先必須可以找到運行phplib所必須
類庫文件,我們可以在php3.ini中設置auto_prepend
變量來支持,phplib分發包中包含一個prepend.php3文件,將auto_prepend指定
為"d:/apache/php/prepend.php3"(帶引號)後,各頁面就會自動包含phplib類庫,我們還可以
將phplib類庫所在目錄加進include變量中,以便可以找到這些文件,當然,最苯的辦法就是指定
phplib的絕對路徑,這可不是個好主意,可移植性太差!
第二步,每一個使用phplib的頁面中,你必須首先調用page_open函數進行初始化。這會告訴
phplib,你現在或將來會用到狀態保存。一個典型的
page_open例子如下:
CODE
page_open(array("sess" => "Example_Session"));
?>

數組變量(sess)用來初始化一些狀態保存對象,注意:必須使用phplib內置名(sess),這些內置
名是你在local.ini中所定義的,page_open
函數必須在頁面內容輸出到瀏覽器之前被調用。php3腳本最後應以page_close()結束,這將會將
有關狀態數據寫回到數據庫中,如果你忘了的話,
結果你應該能想到,哈哈,你的變量全丟了,可不要怪我沒告訴你...

因為phplib使用了Cookies來保存狀態信息,所以page_open()函數必須在頁面內容輸出到瀏覽器
之前被調用, 這裡的頁面內容可以是任何HTML
信息或者空行,如果你發現了錯誤"Oops - SetCookie called after header has been sent",
這表明在page_open()之前向瀏覽器輸出了些什麼,
你要特別留意空行,因為非常難找到,典型的錯誤是在 標記之間輸出了空行,你應檢查
在local.inc和prepend.php3文件中是否包含了空行,
這也是一個非常容易出錯的地方。為了減少出錯的可能,我們可以這樣書寫初始化程序:
CODE
page_open(array("sess" => "Example_Session"));
?>

.....

第三步,具體使用。
當一個用戶訪問了該網站後,隨即用戶的session就開始了,如果用戶的瀏覽器支持cookie的話,
將會建立一個session的id放入cookie,
這個唯一的ID是由PHP3隨機生成,然後又用隨機種子字串進行md5加密過了的,這裡的cookie應該
叫做session cookie,因為這個cookie是不會
寫到用戶硬盤裡去的,當一個session期結束的時候,該cookie也被完結了。如果用戶瀏覽器不支
持cookie的話,那麼 該session的id將會放入url鏈中,
因為是加密過的,所以竊取了也沒用。session ID存放著用戶的有關信息,如用戶已認證、認證
到期時間、用戶權限,和其他一些你可能需要的信息,
方便我們取用。
Session其實就是用戶一次會話的過程。Session並不是僅僅用來跟蹤用戶的註冊,實際上,它還
可以有其它的使用場合,你可以用它來存儲任何你想要
存貯的信息,這些信息可以在用戶隨後訪問的頁面中派上用場,當然前提是那些頁面要使用
PHPLIB。方法很簡單,註冊一個變量後即可在隨後的頁面中使用它,
直至session結束。方法:

CODE
register( "variable_name"); ?>

注意,這裡的variable_name不是變量值,而是變量名,可以先指定變量名,隨後再賦值。你在某
個頁面中可以改變變量的值,隨後的頁面訪問該變量時
會得到改變後的值。變量的類型是多樣的,可以是一個字串,一個數字,一個數組。舉例來說
明:

page_open(array("sess" => "Example_Session"));
$sess->register( "first"); //注意變量名前不需要?#91; $
if (iset( $firstname)) {
$first = $firstname;
}
.....
page_close();
?>
第二頁:
CODE
page_open();//開始session

echo $first;//看看效果

page_close();//保存狀態信息
?>

註冊完一個變量,當頁面最後調用page_close()函數後,各個session變量會被寫回到數據庫中。
如果你忘記調用page_close()函數的話,
變量就不會被寫回數據庫,將出現不可預知的後果。當變量被使用完畢,你不再需要用到時,可
以調用以下函數將變量刪除:
CODE
page_open(array("sess" => "Example_Session"));
...
$sess->unregister( "variable_name");
...
page_close();
?>

PHPLIB 7.0中,使用了一種存儲結構,它允釦A存儲session數據到數據庫中、共享內存中或者
LDAP中。PHPLIB使用了數據庫類,這使得你有
了更多的選擇,你可以選用oracle8,mysql,postgresql等等數據庫來保存狀態信息。

關於phplib中的其它弁鄍H及有關session的其它函數的使用,你可以參看它帶的手冊,或上它的
網站看在線文檔。它的老家在
http://phplib.netuse.de/index.php3
php4的session實現大都從phplib學來的,它也靠cookies保存session id,用文件系統保存變量
(默認情況下)。因此,它的session
變量不能保存對像(事實上能保存對像內容,但沒有意義,因為它是保存在磁盤上的,不是活的對
象,充其量也就是對像屍體。)不過這點的限制不是太
大,我們在大部分情況下都只需要保存變量就行了。當然你也可以將session保存在數據庫中,下
一小節中我們會講到怎樣將session保存在數據庫中。
在php4中由於比php3多了session支持,所以在php.ini文件中也多了session配置選項。下面我們
來看看各項的作用與意義:

CODE

[Session]
session.save_handler = files; handler used to store/retrieve data(用什麼保存session
變量,默認情況下用文件)
session.save_path = c:/temp; argument passed to save_handler(保存session變量的目錄,
在linux/unix下為/tmp,在win下?#93;為你的目錄) ; in the case of files, this is the ; path where data files are stored
session.use_cookies = 1; whether to use cookies(是否使用cookies,當然,在win下別無選
擇)
session.name = PHPSESSID ; name of the session(默認session使用的cookies名,建議不要改動) ; is used as cookie name
session.auto_start = 0; initialize session on request startup(是否自動啟用session,當
為1時,在每頁中就可以不必調用session_start()函數了)
session.cookie_lifetime = 0; lifetime in seconds of cookie(?#93;定 cookie 送到瀏覽器後
的保存時間,單位為秒。缺省值為 0,表示直到瀏覽器關閉。) ; or if 0, until browser is restarted
session.cookie_path = /; the path the cookie is valid for(cookie)(cookies有效路徑)
session.cookie_domain =; the domain the cookie is valid for(cookies有效域名)
session.serialize_handler = php; handler used to serialize data(定義序列化數據的標
識,本弁鄍u有 WDDX 模塊或 PHP 內部使用。缺省值為 php) ; php is the standard serializer of PHP
session.gc_probability = 1; percentual probability that the (?#93;定每次臨時文件開始處
理 (gc, garbage collection) 處理概率。缺省值為 1。 ) ; 'garbage collection' process is started ; on every session initialization
session.gc_maxlifetime = 1440; after this number of seconds, stored(?#93;定保存session
的臨時文件被清除前的存活秒數) ; data will be seen as 'garbage' and ; cleaned up by the gc process
session.referer_check =; check HTTP Referer to invalidate (決定參照到客戶端的
Session 代碼是否要刪除。有時在安全或其它考慮時,會?#93;定不刪除。缺省值為 0。) ; externally stored URLs containing ids
session.entropy_length = 0; how many bytes to read from the file(?#93;定 session 從高熵
值資源讀取的位數。缺省值為 0.)
session.entropy_file =; specified here to create the session id(?#93;定 session 代碼建
立時,使用外部高熵值資源或文件來建立,例如 UNIX 系統上的 /dev/random
或 /dev/urandom。 ) ; session.entropy_length = 16 ; session.entropy_file = /dev/urandom
session.cache_limiter = nocache; set to { nocache,private,public } to (?#93;定session
緩衝限制) ; determine HTTP caching aspects
session.cache_expire = 180; document expires after n minutes(文檔有效期,單位為分鐘)

在windows平台下,php4.01pl2以前的版本會出現?#93;置session.save_path 後出錯的情況,這是
php的一個bug,在php4.01pl2及以後已經修正了。如果你用以前的版本,
你可以將session.save_path?#93;為"./",或?#93;為"/temp",並在你放置php腳本的當前盤根目錄下建一
個名為temp的目錄即可(我的php腳本放在d:apachehtdocs下,則我在d:盤根目錄下建一名為temp
的目錄)。
在php4中有關session的函數主要有以下這些:

session_start: 初始化session,需要用session的每一個頁面最開始處調用。
session_destroy: 結束 session,在需要結束session處調。
session_name: 存取目前 session 名稱。
session_module_name: 存取目前 session 模塊。
session_save_path: 存取目前 session 路徑。
session_id: 存取目前 session id號。
session_register: 註冊新的session變量。
session_unregister: 刪除已註冊session變量。
session_is_registered: 檢查session變量是否註冊。
session_decode: Session 數據解碼。
session_encode: Session 數據?#91;密。

通常情況下我們只需要調用三個函數即可。
即sesssion_start()、session_register()、session_is_registered()。
在需要用到session的每一頁的最開始處調用session_start()函數,
一個典型的使用session的頁面如下:
CODE

....

$var="hello";
session_register("var");//註冊 $var變量,注意沒有 $符號

if(session_is_registered("var"))//檢查變量是否註冊
echo "haha,註冊了!";
else
echo "sorry,還沒有註冊!";

?>

php4中session處理的定制

我們需要擴充6個函數,當然這些函數不需你去調用,對我們來說是透明的。

這幾個函數是:
sess_open( $sess_path, $session_name);

這個函數被session處理程序調用來作初始化工作。需要傳給它的兩個參數是 $sess_path,它對應
你的php.ini文件中的session.save_path
選項; $session_name,它對應php.ini中的session.name 選項。它們具體怎樣工作,請看下面的例
子。

sess_close();

這個函數在頁面結束執行並且session處理程序需要關閉時被調用。(注意,不要和sess_destory
混淆了,它是用來結束session的)

sess_read( $key);

這個函數在session處理程序讀取指定session鍵值( $key)時。
這個函數檢索並返回標識為 $key的session數據.(注意:你不用擔心怎樣序列化和反序列化數據,
如果你不知道這是什麼意思,不要擔心它)

譯者註:序列化是將變量或對像在程序結束或需要時保存在文件中,在下次程序運行或需要時再
調入內存的技術,有別於只保存數據的方法。

sess_write( $key, $val);

這個函數據在session處理程序需要將數據保存時調用,這種情況經常在你的程序結束時發生。
早t責將數據保存在下次能用sess_read( $key)函數檢索的地方。

sess_destroy( $key);

這個函數在需要消毀session時。它負責刪除session並且清除環境。

sess_gc( $maxlifetime);
這個函數負責清理碎片。在這種情況下,它負責刪除過時的session數據。session處理程序會偶
爾調用它們。

現在我們已經清楚了我們提供的函數。

定製程序可以用mysql數據庫或DBM文件保存session數據。取決於你的需要。
如果你決定使用mysql作支持,那需要作以下工作:

首先我們在mysql中創建一個sessions數據庫,並且創建一個sessions表。先運行你的mysql客戶
端並且執行下面的命令:
mysql> CREATE DATABASE sessions;

mysql> GRANT select, insert, update, dele ON sessions.* TO phpsession@localhost
-> IDENTIFIED BY 'phpsession';

mysql> CREATE TABLE sessions (
-> sesskey char(32) not null,
-> expiry int(11) unsigned not null,
-> value text not null,
-> PRIMARY KEY (sesskey)
-> );

下一步,修改session_mysql.php文件的 $SESS_DB* 變量使其匹配你機器上的數據庫設置。

(很抱歉,由於版權原因,我不能把以下代碼中的英文去掉,只好加些註釋了

CODE
/* ------------------------------------------------------------------------

  • session_mysql.php


  • PHP4 MySQL Session Handler

  • Version 1.00

  • by Ying Zhang ( [email protected] )

  • Last Modified: May 21 2000


  • TERMS OF USAGE:


  • You are free to use this library in any way you want, no warranties are

  • expressed or implied. This works for me, but I don't guarantee that it

  • works for you, USE AT YOUR OWN RISK.

  • While not required to do so, I would appreciate it if you would retain

  • this header information. If you make any modifications or improvements,

  • please send them via email to Ying Zhang < [email protected] >.


  • DESCRIPTION:


  • This library tells the PHP4 session handler to write to a MySQL database

  • instead of creating individual files for each session.

  • Create a new database in MySQL called "sessions" like so:

  • CREATE TABLE sessions (

  • sesskey char(32) not null,

  • expiry int(11) unsigned not null,

  • value text not null,

  • PRIMARY KEY (sesskey)

  • );


  • INSTALLATION:


  • Make sure you have MySQL support compiled into PHP4. Then copy this

  • script to a directory that is accessible by the rest of your PHP

  • scripts.
    *確信你的php4有mysql支持,然後把這個腳本拷貝到和你的php腳本有關的目錄。


  • USAGE:?#93;使用方法)


  • Include this file in your scripts before you call session_start(), you

  • don't have to do anything special after that.
    *?#93;含這個文件到你要使用session的文件中,必須在調用session_start()之前,否則,
    *會很慘的,不要怪我沒告訴你。 這樣就不需要再做什麼工作了,還和你以前用session的方法一
    樣。
    */

$SESS_DBHOST = "localhost"; /* database server hostname /
$SESS_DBNAME = "sessions"; /
database name /
$SESS_DBUSER = "phpsession"; /
database user /
$SESS_DBPASS = "phpsession"; /
database password */

$SESS_DBH = "";
$SESS_LIFE = get_cfg_var("session.gc_maxlifetime");

function sess_open( $save_path, $session_name) {
global $SESS_DBHOST, $SESS_DBNAME, $SESS_DBUSER, $SESS_DBPASS, $SESS_DBH;

if (! $SESS_DBH = mysql_pconnect( $SESS_DBHOST, $SESS_DBUSER, $SESS_DBPASS)) {
echo "

  • Can't connect to $SESS_DBHOST as $SESS_DBUSER";
    echo "
  • MySQL Error: ", mysql_error();
    die;
    }

if (! mysql_select_db( $SESS_DBNAME, $SESS_DBH)) {
echo "

  • Unable to select database $SESS_DBNAME";
    die;
    }

return true;
}

function sess_close() {
return true;
}

function sess_read( $key) {
global $SESS_DBH, $SESS_LIFE;

$qry = "SELECT value FROM sessions WHERE sesskey = ' $key' AND expiry > " . time();
$qid = mysql_query( $qry, $SESS_DBH);

if (list( $value) = mysql_fetch_row( $qid)) {
return $value;
}

return false;
}

function sess_write( $key, $val) {
global $SESS_DBH, $SESS_LIFE;

$expiry = time() + $SESS_LIFE;
$value = addslashes( $val);

$qry = "INSERT INTO sessions VALUES (' $key', $expiry, ' $value')";
$qid = mysql_query( $qry, $SESS_DBH);

if (! $qid) {
$qry = "UPDATE sessions SET expiry = $expiry, value = ' $value' WHERE sesskey
= ' $key' AND expiry > " . time();
$qid = mysql_query( $qry, $SESS_DBH);
}

return $qid;
}

function sess_destroy( $key) {
global $SESS_DBH;

$qry = "DELETE FROM sessions WHERE sesskey = ' $key'";
$qid = mysql_query( $qry, $SESS_DBH);

return $qid;
}

function sess_gc( $maxlifetime) {
global $SESS_DBH;

$qry = "DELETE FROM sessions WHERE expiry < " . time();
$qid = mysql_query( $qry, $SESS_DBH);

return mysql_affected_rows( $SESS_DBH);
}

session_set_save_handler(
"sess_open",
"sess_close",
"sess_read",
"sess_write",
"sess_destroy",
"sess_gc");
?>

=================================================================
定制使用dbm文件時的接口

CODE
/* ------------------------------------------------------------------------

  • session_dbm.php

  • PHP4 DBM Session Handler
  • Version 1.00
  • by Ying Zhang ( [email protected] )
  • Last Modified: May 21 2000

  • TERMS OF USAGE:

  • You are free to use this library in any way you want, no warranties are
  • expressed or implied. This works for me, but I don't guarantee that it
  • works for you, USE AT YOUR OWN RISK.
  • While not required to do so, I would appreciate it if you would retain
  • this header information. If you make any modifications or improvements,
  • please send them via email to Ying Zhang < [email protected] >.

  • DESCRIPTION:

  • This library tells the PHP4 session handler to write to a DBM file
  • instead of creating individual files for each session.

  • INSTALLATION:

  • Make sure you have DBM support compiled into PHP4. Then copy this
  • script to a directory that is accessible by the rest of your PHP
  • scripts.
    *確信你的php4有DBM支持。拷貝這個文件在你的php腳本目錄。

  • USAGE:

  • Include this file in your scripts before you call session_start(), you
  • don't have to do anything special after that.
  • 在調用session_start()之前請?#93;含這個文件。之後就不需要作什麼工作了。
    */

$SESS_DBM = "";
$SESS_LIFE = get_cfg_var("session.gc_maxlifetime");

function sess_open( $save_path, $session_name) {
global $SESS_DBM;

$SESS_DBM = dbmopen(" $save_path/ $session_name", "c");
return ( $SESS_DBM);
}

function sess_close() {
global $SESS_DBM;

dbmclose( $SESS_DBM);
return true;
}

function sess_read( $key) {
global $SESS_DBM, $SESS_LIFE;

$var = "";
if ( $tmp = dbmfetch( $SESS_DBM, $key)) {
$expires_at = substr( $tmp, 0, strpos( $tmp, "│"));

if ( $expires_at > time()) {
$var = substr( $tmp, strpos( $tmp, "│") + 1);
}
}

return $var;
}

function sess_write( $key, $val) {
global $SESS_DBM, $SESS_LIFE;

dbmreplace( $SESS_DBM, $key, time() + $SESS_LIFE . "│" . $val);
return true;
}

function sess_destroy( $key) {
global $SESS_DBM;

dbmdele( $SESS_DBM, $key);
return true;
}

function sess_gc( $maxlifetime) {
global $SESS_DBM;

$now = time();
$key = dbmfirstkey( $SESS_DBM);
while ( $key) {
if ( $tmp = dbmfetch( $SESS_DBM, $key)) {
$expires_at = substr( $tmp, 0, strpos( $tmp, "│"));
if ( $now > $expires_at) {
sess_destroy( $key);
}
}

$key = dbmnextkey( $SESS_DBM, $key);
}
}

session_set_save_handler(
"sess_open",
"sess_close",
"sess_read",
"sess_write",
"sess_destroy",
"sess_gc");
?>

=================================================================
具體怎麼用就不用多說了,因為這些函數都是php引擎調用的,與我們無關的。我們只需照上述配
置後就行了,你用的還是以前的session函數。
看看下面的代碼就知道了:)

==================================================================
CODE

Unrecognized handler ( $handler)"; die; } /* start the session and register a simple counter */ session_start(); session_register("count"); /* figure out what we should do, depending on the action */ switch ( $action) { case "increment" : $count = isset( $count) ? $count + 1 : 0; break; case "destroy" : session_destroy(); break; case "gc" : $maxlife = get_cfg_var("session.gc_maxlifetime"); sess_gc( $maxlife); break; default: echo " ```
  • Unknown action ( $action)"; break; } ?>

    Session Test Script

    • Handler:
    • Action:
    • Count:

    Handler:
    Action:

  • ```
    Published At
    Categories with Web编程
    Tagged with
    comments powered by Disqus