使用PHPLIB進(jìn)行Session的管理與認(rèn)證(轉(zhuǎn)載)
發(fā)表時(shí)間:2023-08-08 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]PHPLIB還可以做很多別的事情,例如數(shù)據(jù)庫(kù)類(lèi)。本篇文章只是對(duì)PHPLIB的簡(jiǎn)單介紹。有很多類(lèi)和功能都沒(méi)有提到。你可以到http://phplib.netuse.de去獲取更多的幫助文檔 -----...
PHPLIB還可以做很多別的事情,例如數(shù)據(jù)庫(kù)類(lèi)。本篇文章只是對(duì)PHPLIB的簡(jiǎn)單介紹。有很多類(lèi)和功能都沒(méi)有提到。你可以到http://phplib.netuse.de去獲取更多的幫助文檔
---------------------------------------------------------------------
測(cè)試環(huán)境:標(biāo)準(zhǔn)環(huán)境
首先要說(shuō)明一個(gè)事實(shí),用Web頁(yè)面設(shè)計(jì)需要保存客戶當(dāng)前狀態(tài)的程序時(shí)極為不便,例如在線Shopping,作為一名程序員,你必須時(shí)時(shí)面對(duì)在各個(gè)主頁(yè)之間傳遞的狀態(tài)參數(shù)?蛻舻纳矸菡J(rèn)證、他已做出的選擇、他當(dāng)前的狀態(tài)等等,Web主頁(yè)并不會(huì)替你保存這些狀態(tài)信息,你必須自己小心處理這些參數(shù),這給我們帶來(lái)了太多的不便,利用 http://url?var1=x1&var2=x2 來(lái)在主頁(yè)間傳送參數(shù)實(shí)在太危險(xiǎn),尤其是變量中包含用戶注冊(cè)信息時(shí)很容易被sniff,那么,我們?nèi)绾谓鉀Q這個(gè)問(wèn)題呢?
PHPLIB解決了這個(gè)問(wèn)題,它是在PHP3上的一個(gè)擴(kuò)展,提供了很多類(lèi)庫(kù),使得程序員能很容易地建立一個(gè)交互式Web站點(diǎn),PHPLIB最基本的功能包括用戶認(rèn)證,Session管理,權(quán)限及數(shù)據(jù)庫(kù)的抽象化。
安裝PHPLIB前你必須在你的服務(wù)器上先安裝好php3,PHPLIB可以運(yùn)行在Cgi方式或apache附加模塊方式。PHP3的版本必須時(shí)在3.0.5之上,PHP3早期版本可以在編譯時(shí)使用參數(shù) --enable-foce-cgi-redirect來(lái)獲得支持,如果不這么做的話,會(huì)出現(xiàn)安全問(wèn)題。PHP3的配置中 track_vars 需要設(shè)置為 enabled。同時(shí)需要一個(gè)數(shù)據(jù)庫(kù),PHPLIB支持MySQL、Oracle、ODBC、PostgreSQL、Sybase。
第一步,PHPLIB的類(lèi)庫(kù)需要根據(jù)系統(tǒng)進(jìn)行初始化,你可以修改local.inc文件,其中包含著一些基本參數(shù),你可以根據(jù)自己機(jī)器的情況來(lái)進(jìn)行修改。
我們說(shuō)明一下PHPLIB的工作原理,每一個(gè)使用PHPLIB的頁(yè)面首先必須可以找到運(yùn)行PHPLIB的必須類(lèi)庫(kù)文件,我們可以在php3.ini中設(shè)置auto_prepend變量來(lái)支持,PHPLIB分發(fā)包中包含一個(gè)prepend.php3文件,將auto_prepend指定為prepend.php3后,各頁(yè)面就會(huì)自動(dòng)包含PHPLIB類(lèi)庫(kù),我們還可以將PHPLIB類(lèi)庫(kù)所在目錄加進(jìn)include變量中,以便可以找到這些文件,當(dāng)然,最苯的辦法就是指定絕對(duì)路徑,這可不是個(gè)好主意!
第二步,每一個(gè)使用PHPLIB的頁(yè)面中,你必須使用函數(shù)page_open進(jìn)行初始化。這會(huì)告訴PHPLIB,你現(xiàn)在或?qū)?lái)會(huì)用到狀態(tài)保存。一個(gè)典型的page_open例子包含到了認(rèn)證、Session、權(quán)限:
< ?php
page_open(array( "sess" => "Cms_Session", "auth" => "Cms_Auth", "perm" => "Cms_Perm"));
?>
數(shù)組變量(sess,auth,perm)用來(lái)初始化一些狀態(tài)保存對(duì)象,注意:必須使用PHPLIB內(nèi)置名(sess,auth,perm),這些內(nèi)置名是你在local.ini中所定義的,page_open函數(shù)必須在頁(yè)面內(nèi)容輸出到瀏覽器之前被調(diào)用。(如果你將來(lái)不會(huì)用到認(rèn)證的話,可以不初始化sess),php3腳本最后應(yīng)以page_close()結(jié)束,這將會(huì)將有關(guān)狀態(tài)數(shù)據(jù)寫(xiě)回到數(shù)據(jù)庫(kù)中,如果你忘了的話,將會(huì),哈哈哈。。。
因?yàn)镻HPLIB使用了Cookies來(lái)保存狀態(tài)信息,所以page_open()函數(shù)必須在頁(yè)面內(nèi)容輸出到瀏覽器之前被調(diào)用, 這里的頁(yè)面內(nèi)容可以是任何HTML信息或者空行,如果你發(fā)現(xiàn)了錯(cuò)誤"Oops - SetCookie called after header has been sent",這表明在page_open()之前向?yàn)g覽器輸出了些什么,你要特別留意空行,因?yàn)榉浅ky找到,典型的錯(cuò)誤是在< ? 和 ?>標(biāo)記之間輸出了空行,你應(yīng)檢查在local.inc和prepend.php3文件中是否包含了空行,這也是一個(gè)非常容易出錯(cuò)的地方。
PHP使用了一種比基本認(rèn)證方法更為復(fù)雜的架構(gòu),這使得安全有了更好的保證。
舉例來(lái)說(shuō),對(duì)于你想要限制訪問(wèn)的頁(yè)面,會(huì)首先使用page_open來(lái)調(diào)用"auth" => "auth_class" ,初始化認(rèn)證狀態(tài)對(duì)象后,狀態(tài)就會(huì)被保存起來(lái),隨后當(dāng)客戶再訪問(wèn)別的頁(yè)面的時(shí)候,認(rèn)證系統(tǒng)就會(huì)首先檢測(cè)用戶的身份是否已經(jīng)經(jīng)過(guò)認(rèn)證。
讓我們解釋一下,當(dāng)一個(gè)用戶第一次訪問(wèn)頁(yè)面時(shí),他的身份未經(jīng)過(guò)認(rèn)證,PHPLIB會(huì)調(diào)用一個(gè)注冊(cè)窗口(并非在WINDOWS中的彈出窗口),你可以自己設(shè)計(jì)注冊(cè)窗口的樣式,當(dāng)用戶輸入他的用戶名與口令,并按下提交鈕后,身份認(rèn)證工作就開(kāi)始了,隨后的情況有些復(fù)雜,讓我們慢慢解釋……
這里分兩種情況,如果用戶的瀏覽器不能兼容JavaScript的話,認(rèn)證工作就象詢問(wèn)嫌疑犯一樣,用戶名與口令被送往服務(wù)器,與存放在那里的數(shù)據(jù)進(jìn)行比較。如果用戶的瀏覽器與JavaScript兼容,這就麻煩一些了,PHPLIB首先會(huì)在客戶端的頁(yè)面中放入一個(gè)用來(lái)加密的種子字串,名叫“challenge”,當(dāng)用戶提交該頁(yè)面時(shí),用戶的用戶名、口令和challenge字串會(huì)使用md5的加密方式進(jìn)行加密,生成一個(gè)加密字串,將該加密字串與用戶名提交給服務(wù)器。當(dāng)服務(wù)器收到用戶名和加密后的字串后,他根據(jù)數(shù)據(jù)庫(kù)中的用戶名與口令和得到的種子進(jìn)行md5運(yùn)算,將生成的字串與用戶提交的字串進(jìn)行比較,如果符合的話,說(shuō)明用戶身份是正確的,就允許用戶進(jìn)行隨后的訪問(wèn)。這種方法的好處是:用戶不用提交密碼,這使得認(rèn)證比較安全。
Session 管理
其實(shí)Session的管理和身份認(rèn)證非常接近,當(dāng)一個(gè)用戶的身份認(rèn)證過(guò)了后,隨即用戶的session就開(kāi)始了,如果用戶的瀏覽器支持cookie的話,將會(huì)建立一個(gè)session的id放入cookie,這個(gè)唯一的ID是由PHP3隨機(jī)生成,然后又用隨機(jī)種子
字串進(jìn)行md5加密過(guò)了的,這里的cookie應(yīng)該叫做session cookie,因?yàn)檫@個(gè)cookie是不會(huì)寫(xiě)到用戶硬盤(pán)里去的,當(dāng)一個(gè)session進(jìn)行完的時(shí)候,該cookie也被完結(jié)了。如果用戶瀏覽器不支持cookie的話,那么 該session的id將會(huì)放入url鏈中,因?yàn)槭羌用苓^(guò)的,所以竊取了也沒(méi)用。session id存放著用戶的有關(guān)信息,如用戶已認(rèn)證、認(rèn)證到期時(shí)間、用戶權(quán)限,和其他一些你可能需要的信息,方便我們?nèi)∮谩?
Session其實(shí)就是用戶一次會(huì)話的過(guò)程。Session的管理并不是僅僅用來(lái)跟蹤用戶的注冊(cè),實(shí)際上,它還可以脫離認(rèn)證來(lái)使用,你可以用它來(lái)存儲(chǔ)任何你想要存貯的信息,這些信息可以在用戶隨后訪問(wèn)的頁(yè)面中派上用場(chǎng),當(dāng)然前提是那些頁(yè)面要使用PHPLIB。方法很簡(jiǎn)單,注冊(cè)一個(gè)變量后即可在隨后的頁(yè)面中使用它,直至session結(jié)束。方法:
< ?php $sess->register( "variable_name"); ?>
注意,這里的variable_name不是變量值,而是變量名,可以先指定變量名,隨后再賦值。你在某個(gè)頁(yè)面中可以改變變量的值,隨后的頁(yè)面訪問(wèn)該變量時(shí)會(huì)得到改變后的值。變量的類(lèi)型是多樣的,可以是一個(gè)字串,一個(gè)數(shù)字,一個(gè)數(shù)組,甚至一個(gè)對(duì)象。舉例來(lái)說(shuō)明:
< ?php
$sess->register( "first");
if (check($firstname)) {
$first = $firstname;
}
?>
注意:這里有一點(diǎn)很重要。你可以先注冊(cè)一個(gè)變量隨后再對(duì)它賦值,這樣非常有效,我們大可以在腳本的任何地方定義變量而不賦值,而在隨后的頁(yè)面中再賦值,這樣方便集中定義變量。大家可能注意到了,上面的例子中我們沒(méi)有簡(jiǎn)單的對(duì)變量賦值,處于安全的考慮,你不應(yīng)該輕率地將表單數(shù)據(jù)放入變量。上例中,我們對(duì)變量進(jìn)行了檢查,然后才對(duì)變量賦值。這是一個(gè)很好的習(xí)慣。大家應(yīng)該注意。
注冊(cè)完一個(gè)變量,當(dāng)頁(yè)面最后調(diào)用page_close()函數(shù)后,各個(gè)session變量會(huì)被寫(xiě)回到數(shù)據(jù)庫(kù)中,如果你忘記調(diào)用page_close()函數(shù)的話,變量就不會(huì)被寫(xiě)回?cái)?shù)據(jù)庫(kù),將出現(xiàn)不可予知的后果。當(dāng)變量被使用完畢后,你不在需要用到了,可以調(diào)用以下函數(shù)將變量刪除:
< ?php
$sess->unregister( "variable_name");
?>
PHPLIB 7.0中,使用了一種存儲(chǔ)結(jié)構(gòu),它允許你存儲(chǔ)session數(shù)據(jù)到數(shù)據(jù)庫(kù)中、共享內(nèi)存中或者LDAP中。PHPLIB使用了數(shù)據(jù)庫(kù)類(lèi),這使得你有了更多的選擇。
權(quán)限管理
權(quán)限是和認(rèn)證分不開(kāi)的。當(dāng)一個(gè)用戶的身份被確認(rèn)以后,你可以接著來(lái)確定他的級(jí)別及權(quán)限。當(dāng)然,你必須先調(diào)用page_open來(lái)初始化"perm"對(duì)象。檢查用戶權(quán)限的命令如下:
< ?php
$perm->check( "permission_level");
?>
這條命令會(huì)檢查用戶是否符合你指定的級(jí)別,指定的級(jí)別應(yīng)在local.inc文件中已經(jīng)定義好,你可以自己定義各種級(jí)別。如果用戶被檢查出不符合級(jí)別。則perm_invalid()函數(shù)自動(dòng)被調(diào)用。你可以建立自己的perm_invalid函數(shù)。
以下是PHPLIB中檢查權(quán)限的另一種方法:
< ?php
$perm->have_perm( "permission_level");
?>
have_perm與check函數(shù)不同,它只返回true或false,但并不退出腳本,這樣我們可以更好的控制程序流程。
< ?php
if ($perm->have_perm( "guest"))
{ //do something; }
elseif ($perm->have_perm( "admin"))
{ //do something else; }
else { //yet something else; }
?>