php會(huì)話(huà)控制:session與cookie詳解
來(lái)源:易賢網(wǎng) 閱讀:828 次 日期:2016-06-22 10:42:29
溫馨提示:易賢網(wǎng)小編為您整理了“php會(huì)話(huà)控制:session與cookie詳解”,方便廣大網(wǎng)友查閱!

本文介紹了php會(huì)話(huà)控制,主要闡述以下幾點(diǎn)內(nèi)容:

• 會(huì)話(huà)控制的產(chǎn)生背景/概念

• cookie的維護(hù)與生命周期(有效時(shí)間)

• session的維護(hù)與生命周期(回收機(jī)制)

• cookie與session之間的區(qū)別與聯(lián)系

• 問(wèn)題1:禁用cookie后session為什么會(huì)失效?

• 問(wèn)題2:ie瀏覽器下丟失session,每次刷新頁(yè)面,都會(huì)生成新的sessionid(firefox瀏覽器正常)

• session、cookie簡(jiǎn)單實(shí)例

理解會(huì)話(huà)控制的概念

理解一個(gè)概念就需要理解他的背景及產(chǎn)生的原因,這里引入web環(huán)境及其http協(xié)議。會(huì)話(huà)控制產(chǎn)生的背景:

閱讀過(guò)http協(xié)議相關(guān)資料的同學(xué)都會(huì)知道http協(xié)議是web服務(wù)器與客戶(hù)端(瀏覽器)相互通信的協(xié)議,它是一種無(wú)狀態(tài)協(xié)議,所謂無(wú)狀態(tài),指的是不會(huì)維護(hù)http請(qǐng)求數(shù)據(jù),http請(qǐng)求是獨(dú)立的,不持久的。也就是說(shuō)http協(xié)議沒(méi)有一個(gè)內(nèi)建的機(jī)制來(lái)維護(hù)兩個(gè)事務(wù)之間的狀態(tài)或者說(shuō)是關(guān)系吧。當(dāng)一個(gè)用戶(hù)在請(qǐng)求一個(gè)頁(yè)面后再去請(qǐng)求另外一個(gè)頁(yè)面時(shí),http將無(wú)法告訴我們這兩個(gè)請(qǐng)求是否來(lái)自同一個(gè)用戶(hù)。

由此我們就會(huì)覺(jué)得很奇怪了,平時(shí)我們?cè)谡搲涮踊螂娚叹W(wǎng)站購(gòu)物時(shí),只要我們?cè)谶@個(gè)站點(diǎn)內(nèi),不論我們?cè)趺刺D(zhuǎn),從一個(gè)頁(yè)面跑到另一個(gè)頁(yè)面,網(wǎng)站總會(huì)記得我是誰(shuí),比如告訴你購(gòu)買(mǎi)了哪些東西。這是怎么做到的呢,估計(jì)大家猜到了,這就是運(yùn)用了http會(huì)話(huà)控制。在網(wǎng)站中跟蹤一個(gè)變量,通過(guò)對(duì)變量的跟蹤,使多個(gè)請(qǐng)求事物之間建立聯(lián)系,根據(jù)授權(quán)和用戶(hù)身份顯示不同的內(nèi)容、不同頁(yè)面。

php session會(huì)話(huà)控制:

php的session會(huì)話(huà)是通過(guò)唯一的會(huì)話(huà)id來(lái)驅(qū)動(dòng)的,會(huì)話(huà)id是一個(gè)加密的隨機(jī)數(shù)字,由php生成,在會(huì)話(huà)的生命周期中都會(huì)保存在客戶(hù)端。我們知道客戶(hù)端(也就是瀏覽器)保存數(shù)據(jù)的地方只有cookie,所以php的會(huì)話(huà)id一般保存在用戶(hù)機(jī)器的cookie中。了解cookie后我們知道,瀏覽器是可以禁用cookie的,這樣會(huì)話(huà)就會(huì)失效。所以php會(huì)話(huà)控制還有一種模式,就是在url中傳遞會(huì)話(huà)id。如果在瀏覽網(wǎng)站時(shí)我們稍加留心的話(huà),有些url中有一串看起來(lái)像隨機(jī)數(shù)字的字符串,那么其實(shí)很有可能就是url形式的會(huì)話(huà)控制。

講到這里,有些人可能會(huì)有疑問(wèn)了,客戶(hù)端只是保存一個(gè)會(huì)話(huà)id,那么會(huì)話(huà)控制中保存的會(huì)話(huà)變量比如你購(gòu)物時(shí)買(mǎi)的物品列表等,它們是存放在哪個(gè)地方的呢?很顯然,會(huì)話(huà)變量是在服務(wù)器端使用的,那么這些會(huì)話(huà)變量必定存放在服務(wù)器端。默認(rèn)情況下,會(huì)話(huà)變量保存在服務(wù)器的普通文件中(也可以自己配置使用數(shù)據(jù)庫(kù)來(lái)保存,可以google一下),會(huì)話(huà)id的作用就像是一把鑰匙,在服務(wù)器端保存會(huì)話(huà)的文件中找到該會(huì)話(huà)id對(duì)應(yīng)的會(huì)話(huà)變量,比如購(gòu)買(mǎi)物品的列表。

那么會(huì)話(huà)控制的整個(gè)過(guò)程可能就像這個(gè)樣子,用戶(hù)登錄或者第一次瀏覽某個(gè)站點(diǎn)的頁(yè)面時(shí),該站點(diǎn)會(huì)生成一個(gè)php的會(huì)話(huà)id并通過(guò)cookie發(fā)送到客戶(hù)端(瀏覽器)。當(dāng)用戶(hù)點(diǎn)擊該站點(diǎn)的另一個(gè)頁(yè)面時(shí),瀏覽器開(kāi)始連接這個(gè)url。在連接之前,瀏覽器會(huì)先搜索本地保存的cookie,如果在cookie中有任何與正在連接的url相關(guān)的cookie,就將它提交到服務(wù)器。而剛好在登陸或第一次連接時(shí),已經(jīng)產(chǎn)生了一個(gè)與該網(wǎng)站url相關(guān)的cookie(保存的會(huì)話(huà)id),所以當(dāng)用戶(hù)再次連接這個(gè)站點(diǎn)時(shí),站點(diǎn)就可以通過(guò)這個(gè)會(huì)話(huà)id識(shí)別出用戶(hù),從服務(wù)器的會(huì)話(huà)文件中取出與這個(gè)會(huì)話(huà)id相關(guān)的會(huì)話(huà)變量,從而保持事務(wù)之間的連續(xù)。

接下來(lái)我們了解下兩個(gè)重要的概念:cookie和session

關(guān)于cookie的維護(hù)與生命周期

cookie是在服務(wù)器端被創(chuàng)建并寫(xiě)回到客戶(hù)端瀏覽器,瀏覽器接到響應(yīng)頭中關(guān)于寫(xiě)cookie的指令則在本地臨時(shí)文件夾中。

創(chuàng)建了一個(gè)cookie文件,其中保存了你的cookie內(nèi)容,cookie內(nèi)容的存儲(chǔ)是鍵值對(duì)的方式,鍵和值都只能是字符串。例如:

文件:cookie:administrator@localhost/

內(nèi)容格式:voteid100101localhost/15361167667230343893360385046430343691*

cookie的創(chuàng)建:

代碼如下:

setcookie()函數(shù)設(shè)置cookie,函數(shù)原型如下

setcookie(name, value, expire, path, domain);

注釋?zhuān)篶ookie標(biāo)題頭必須在發(fā)送其他標(biāo)題頭之前發(fā)送,否則就無(wú)效(這是cookie的限制,而不是php的限制)。在發(fā)送 cookie 時(shí),cookie 的值會(huì)自動(dòng)進(jìn)行 url 編碼,在取回時(shí)進(jìn)行自動(dòng)解碼(為防止 url 編碼,請(qǐng)使用 setrawcookie() 取而代之)。

cookie的維護(hù):

cooke有四個(gè)標(biāo)識(shí)符:cookie的name,domain,path,secure標(biāo)記。要想在將來(lái)改變這個(gè)cookie的值,需要發(fā)送另一個(gè)具有相同cookie name,domain,path的set-cookie消息頭,這將以一個(gè)新

的值來(lái)覆蓋原來(lái)cookie的值。然而,如果僅僅只是改變這些選項(xiàng)的某一個(gè)也會(huì)創(chuàng)建一個(gè)完全不同的cookie,如只是更改了name值。

cookie失效時(shí)間:

可以設(shè)置過(guò)期時(shí)間,如果不設(shè)置則是會(huì)話(huà)級(jí)別的,即關(guān)閉瀏覽器就會(huì)消失。當(dāng)cookie創(chuàng)建時(shí)包含了失效日期,這個(gè)失效日期則關(guān)聯(lián)了以name-domain-path-secure為標(biāo)識(shí)的cookie。要改變一個(gè)cookie的失效日期,你必須指定同樣的組合。當(dāng)改變一個(gè)cookie的值時(shí),你不必每次都設(shè)置失效日期,因?yàn)樗皇莄ookie標(biāo)識(shí)信息的組成部分。例如:

代碼如下:

setcookie(vote ,$id+1,time()+3600*24);

setcookie(vote,$id);

在cookie上的失效日期并沒(méi)有改變,因?yàn)閏ookie的標(biāo)識(shí)符是相同的。實(shí)際上,只有你手工的改變cookie的失效日期,否則其失效日期不會(huì)改變。這意味著在同一個(gè)會(huì)話(huà)中,一個(gè)會(huì)話(huà)cookie可以變成一個(gè)持久化cookie(一個(gè)可以在多個(gè)會(huì)話(huà)中存在的),反之則不可。為了要將一個(gè)持久化cookie變?yōu)橐粋€(gè)會(huì)話(huà)cookie,你必須刪除這個(gè)持久化cookie,這只要設(shè)置它的失效日期為過(guò)去某個(gè)時(shí)間之后再創(chuàng)建一個(gè)同名的會(huì)話(huà)cookie就可以實(shí)現(xiàn)。

需要記得的是失效日期是以瀏覽器運(yùn)行的電腦上的系統(tǒng)時(shí)間為基準(zhǔn)進(jìn)行核實(shí)的。沒(méi)有任何辦法來(lái)來(lái)驗(yàn)證這個(gè)系統(tǒng)時(shí)間是否和服務(wù)器的時(shí)間同步,所以當(dāng)服務(wù)器時(shí)間和瀏覽器所處系統(tǒng)時(shí)間存在差異時(shí)這樣的設(shè)置會(huì)出現(xiàn)錯(cuò)誤。

cookie自動(dòng)刪除:

cookie會(huì)被瀏覽器自動(dòng)刪除,通常存在以下幾種原因:

會(huì)話(huà)cooke(session cookie)在會(huì)話(huà)結(jié)束時(shí)(瀏覽器關(guān)閉)會(huì)被刪除

持久化cookie(persistent cookie)在到達(dá)失效日期時(shí)會(huì)被刪除,如:

代碼如下:

setcookie(vote, , time()-3600);

如果瀏覽器中的cookie限制到達(dá),那么cookies會(huì)被刪除以為新建cookies創(chuàng)建空間。

關(guān)于session的維護(hù)與生命周期

session是由應(yīng)用服務(wù)器維持的一個(gè)服務(wù)器端的存儲(chǔ)空間,用戶(hù)在連接服務(wù)器時(shí),會(huì)由服務(wù)器創(chuàng)建生成一個(gè)唯一的sessionid,用該sessionid為標(biāo)識(shí)符來(lái)存取服務(wù)器端的session存儲(chǔ)空間,在會(huì)話(huà)期間,分配給客戶(hù)端的唯一sessionid,用來(lái)標(biāo)識(shí)當(dāng)前用戶(hù),與其他用戶(hù)進(jìn)行區(qū)分。通過(guò)sessionid接受每一次訪問(wèn)的請(qǐng)求,從而識(shí)別當(dāng)前用戶(hù),跟蹤和保持用戶(hù)的具體資料,以及session變量,可在session中存儲(chǔ)數(shù)字或文字資料.比如session_name.這些信息都保存在服務(wù)器端。當(dāng)然,sessionid也可以作為會(huì)話(huà)信息保存到數(shù)據(jù)庫(kù)中,進(jìn)行session持久化。這樣可以跟蹤用戶(hù)的登陸次數(shù)、在線與否、在線時(shí)間等從而維護(hù)http無(wú)狀態(tài)事物之間的關(guān)系。session的內(nèi)容存儲(chǔ)是鍵值對(duì)的列表,鍵是字符串類(lèi)型,session的存儲(chǔ)更方便,值可以是對(duì)象。

在session會(huì)話(huà)期間,session會(huì)分別保存在客戶(hù)端和服務(wù)器端兩個(gè)文件,客戶(hù)端可以是cookie方式保存的sessionid(默認(rèn)的保存方式)或通過(guò)url字符串形式傳遞。服務(wù)器端一般以文本的形式保存在指定的session目錄中。在服務(wù)器端我們可以通過(guò)session.use_cookies來(lái)控制客戶(hù)端使用哪一種保存方式。如果定義為cookie保存方式,我們可以通過(guò)session.cookie_lifetime(默認(rèn)值0,閉瀏覽器就清除)來(lái)控制被保存在client上的cookie的有效期。而如果客戶(hù)端用cookie方式保存的sessionid,則使用“臨時(shí)”的cookie保存(cookie的名稱(chēng)為phpsessid,通過(guò)firebug你可以了解到詳細(xì)的信息,該名稱(chēng)你可以通過(guò)php.ini session.name進(jìn)行更改),用戶(hù)提交頁(yè)面時(shí),會(huì)將這一sessionid提交到服務(wù)器端,來(lái)存取session數(shù)據(jù)。這一過(guò)程,是不用開(kāi)發(fā)人員干預(yù)的。

session的創(chuàng)建:

代碼如下:

session_start() //開(kāi)始一個(gè)會(huì)話(huà)及返回已經(jīng)存在會(huì)話(huà)

功能:初始化session,也標(biāo)識(shí)著session生命周期的開(kāi)始。要使用session,必須初始化一個(gè)session環(huán)境,有點(diǎn)類(lèi)似于oop概念中調(diào)用構(gòu)造函數(shù)構(gòu)創(chuàng)建對(duì)象實(shí)例一樣。session初始化操作,聲明一個(gè)全局?jǐn)?shù)組$_session,映射寄存在內(nèi)存的session數(shù)據(jù)。如果session文件已經(jīng)存在,并且保存有session數(shù)據(jù),session_start()則會(huì)讀取session數(shù)據(jù),填入$_session中,開(kāi)始一個(gè)新的session生命周期。

說(shuō)明:這個(gè)函數(shù)沒(méi)有參數(shù),且返回值為true,如果使用基于cookie的sessin,那么在session_satrt()之前不能有任何的輸出,包括空白

如果在php.ini中session.auto_start=1開(kāi)啟,則在每個(gè)頁(yè)面執(zhí)行session_start(),不需要手工設(shè)置,該選項(xiàng)默認(rèn)為關(guān)閉狀態(tài),開(kāi)啟后不能將對(duì)象放入session中。

session id:

用戶(hù)session唯一標(biāo)識(shí)符,隨機(jī)生成的一串字符串,具有唯一性,隨機(jī)性。主要用于區(qū)分其它用戶(hù)的session數(shù)據(jù)。用戶(hù)第一次訪問(wèn)web頁(yè)面的時(shí)候,php的session初始化函數(shù)調(diào)用會(huì)分配給當(dāng)前來(lái)訪用戶(hù)一個(gè)唯一的id,也稱(chēng)之為session_id。

獲得session_id():

代碼如下:

echo $_cookie['phpsessid'].'<br/>';

echo $_cookie[session_name()].'<br/>';

echo session_id().'<br/>';

session數(shù)據(jù):

我們把需要通過(guò)session保存的用戶(hù)狀態(tài)信息,稱(chēng)為用戶(hù)session數(shù)據(jù),也稱(chēng)為session data。一般是在當(dāng)前session生命周期內(nèi),相應(yīng)的$_session數(shù)據(jù)。一旦調(diào)用了session_start()初始化session,就意味著開(kāi)始了一個(gè)session生命周期。也就是宣布了,可以使用相關(guān)函數(shù)操作$_session來(lái)管理session數(shù)據(jù)。這個(gè)session生命周期產(chǎn)生的數(shù)據(jù)并沒(méi)有實(shí)時(shí)地寫(xiě)入session文件,而是通過(guò)$_session變量寄存在內(nèi)存中。$_session是一個(gè)全局變量,類(lèi)型是array,映射了session生命周期的session數(shù)據(jù),寄存在內(nèi)存中。在session初始化的時(shí)候,從session文件中讀取數(shù)據(jù),填入該變量中。在session(生命周期)結(jié)束時(shí),將$_session數(shù)據(jù)寫(xiě)回session文件。

注冊(cè)一個(gè)會(huì)話(huà)變量:

從php4.1以后,會(huì)話(huà)變量保存在超級(jí)全局?jǐn)?shù)組$_session中。要?jiǎng)?chuàng)建一會(huì)話(huà)變量,只需要在數(shù)組中設(shè)置一個(gè)元素,如:

代碼如下:

$_session['domain'] = blog.jb51.net;

$_session['poll']=$_session[poll] + 1;

使用一個(gè)會(huì)話(huà)變量:

代碼如下:

echo $_session['blogdomain']; //打印出blog.jb51.net,使用會(huì)話(huà)前必須先使用session_start()函數(shù)啟動(dòng)一個(gè)會(huì)話(huà)

注銷(xiāo)session變量/銷(xiāo)毀會(huì)話(huà):

代碼如下:

unset($_session); //銷(xiāo)毀單個(gè)會(huì)話(huà)變量

如:unset($_session['blogdomain']);

#unset($_session)這個(gè)函數(shù)會(huì)將全局變量$_session銷(xiāo)毀,而且還沒(méi)有可行的辦法將其恢復(fù)。用戶(hù)也不再可以注冊(cè)$_session變量,所以此函數(shù)千萬(wàn)不可使用。

session_unset(); //多項(xiàng)釋放。將所有登陸在session文件里的變量釋放出來(lái)

#在session生命周期,從當(dāng)前session中注銷(xiāo)全部session數(shù)據(jù),讓$_session成為一個(gè)空數(shù)組。它與unset($_session)的區(qū)別在于:unset直接刪除$_session變量,釋放內(nèi)存資源;另一個(gè)區(qū)別在于,session_unset()僅在session生命周期能夠操作$_session數(shù)組,而unset()則在整個(gè)頁(yè)面(page)生命周期都能操作$_session數(shù)組。session_unset()同樣不進(jìn)行任何io操作,只影響$_session數(shù)組。

$_session=array(); //多項(xiàng)釋放,釋放所有登錄在$_session參數(shù)里的變量

session_destroy();

#當(dāng)使用完一個(gè)會(huì)話(huà)后,首先應(yīng)該注銷(xiāo)所有的變量,然后再調(diào)用該函數(shù)結(jié)束當(dāng)前的會(huì)話(huà),并清空會(huì)話(huà)中的所有資源,刪除服務(wù)器上的session文件.該函數(shù)不會(huì)unset(釋放)和當(dāng)前session相關(guān)的全局變量,也不會(huì)刪除客戶(hù)端的session cookie

#如果說(shuō)session_start()初始化一個(gè)session的話(huà),而它則注銷(xiāo)一個(gè)session。意味著session生命周期結(jié)束了。在session生命周期結(jié)整后, session_unset, $_session['domain'] 都將不能操作$_session數(shù)組,而$_session數(shù)組依然可以被unset()等函數(shù)操作。這時(shí),session意味著是未定義的,而$_session依然是一個(gè)全局變量,他們脫離了關(guān)映射關(guān)系。

通過(guò)session_destroy()注銷(xiāo)session,除了結(jié)束session生命周期外,它還會(huì)刪除sesion文件,但不會(huì)影響當(dāng)前$_session變量。即它會(huì)產(chǎn)生一個(gè)io操作。

備注:

1、php默認(rèn)的session是基于cookie的,如果要?jiǎng)h除cookie的話(huà),必須借助setcookie()函數(shù)

2、session_unset()和unset()函數(shù)區(qū)別:

在session生命周期,session_unset()從當(dāng)前session中注銷(xiāo)全部session數(shù)據(jù),讓$_session成為一個(gè)空數(shù)組。它與unset($_session)的區(qū)別在于:unset直接刪除$_session變量,釋放內(nèi)存資源;另一個(gè)區(qū)別在于,session_unset()僅在session生命周期能夠操作$_session數(shù)組,而unset()則在整個(gè)頁(yè)面(page)生命周期都能操作$_session數(shù)組。session_unset()同樣不進(jìn)行任何io操作,只影響$_session數(shù)組。

session生命周期(session lifetime):session失效時(shí)間與過(guò)期回收機(jī)制

我們把初始化session開(kāi)始,直到注銷(xiāo)session這段期間,稱(chēng)為session生命周期

默認(rèn)的,php會(huì)將session保存在php.ini配置中session.save_path設(shè)定的目錄下,文件名為這個(gè)樣子:sess_ves0d7uvdsab9k6sig73mnn592。每一個(gè)文件對(duì)應(yīng)了一個(gè)session(會(huì)話(huà))。session文件格式大致如下:

代碼如下:

poll_200|i:1;poll_100|i:3; //#變量名|類(lèi)型:長(zhǎng)度:值

設(shè)置session的生命周期:

php session是基于cookie的,所以要設(shè)置session的生命周期,首先要設(shè)置cookie的失效時(shí)間。因?yàn)樵诳蛻?hù)端(如瀏覽器)登錄網(wǎng)站時(shí),session 是否有用,首先找客戶(hù)端是否有 cookie,通過(guò)cookie 中的 session id 去找服務(wù)器上的文件。

代碼如下:

session_start();

$lifetime = 24 * 3600; // 保存一天

setcookie(session_name(), session_id(), time() + $lifetime, /);

其實(shí)php5 session還提供了一個(gè)函數(shù) session_set_cookie_params(); 來(lái)設(shè)置php5 session的生存期的,該函數(shù)必須在 session_start() 函數(shù)調(diào)用之前調(diào)用:

代碼如下:

$lifetime = 24 * 3600; // 保存一天

session_set_cookie_params($lifetime);

session_start();

在服務(wù)器端,php如何判斷session文件是否過(guò)期?

代碼如下:

session.gc_maxlifetime = 1440 (初始值)

#設(shè)置session存活時(shí)間,單位是秒。每次gc啟動(dòng)后, 會(huì)通過(guò)stat得到session文件最后訪問(wèn)的unix時(shí)間,通過(guò)現(xiàn)在時(shí)間減去文件最后訪問(wèn)時(shí)間之間大于session.gc_maxlifetime,則會(huì)刪除該文件。

如果最后的修改時(shí)間到現(xiàn)在超過(guò)了session.gc_maxlifetime(默認(rèn)是1440)秒,也就是說(shuō)在這里設(shè)置的時(shí)間內(nèi),該文件沒(méi)有被修改過(guò),這個(gè)session文件就被認(rèn)為是過(guò)期了,由于php5的session采用被動(dòng)的回收機(jī)制,過(guò)期的session文件不會(huì)自己消失,而是通過(guò)觸發(fā)“回收”來(lái)處理過(guò)期的session,那么在下一次session回收的時(shí)候,如果這個(gè)文件仍然沒(méi)有被更改過(guò),這個(gè)session文件就會(huì)被刪除(session就過(guò)期了)。

session回收何時(shí)發(fā)生?

默認(rèn)情況下,每一次php請(qǐng)求,就會(huì)有1%的概率發(fā)生回收,所以可能簡(jiǎn)單的理解為“每100次php請(qǐng)求就可能有一次回收概率發(fā)生”。這個(gè)概率是通過(guò)以下參數(shù)控制的:

代碼如下:

session.gc_probability = 1 (初始值)

session.gc_divisor = 100 (初始值)

#由這二個(gè)函數(shù)決定了啟用gc的概率,默認(rèn)是1/1000。也就是說(shuō),每一千次用戶(hù)請(qǐng)求中有一次會(huì)啟動(dòng)gc回收session。啟動(dòng)gc進(jìn)程不宜過(guò)于頻繁。過(guò)于頻繁訪問(wèn)的網(wǎng)站,并發(fā)量大的網(wǎng)站,可減小php gc的啟動(dòng)頻率。php gc回收session會(huì)降低php的執(zhí)行效率。

這兩個(gè)合起來(lái)就是啟動(dòng)gabadge collection(gc)進(jìn)程管理概率的,在session初使化時(shí)(session_start())。gabadge collection啟動(dòng)后跟蹤session信息文件。其啟動(dòng)概率為session.gc_probability/session.gc_divisor。也就是說(shuō)不是每個(gè)session信息文件都有100%的被系統(tǒng)當(dāng)作垃圾來(lái)處理的。如果直接關(guān)閉瀏覽器的話(huà),session信息文件很多情況下都是留在了服務(wù)器上,如果把概率改成了100%,雖然gabadge collection百分之百被啟動(dòng)了,但是這會(huì)對(duì)服務(wù)器添加負(fù)荷,也就失去了gc本身的意義了。

補(bǔ)充說(shuō)明:

1、假設(shè)這種情況session.gc_maxlifetime=1440,如果某個(gè)session文件最后修改時(shí)間是1440秒之前,那么在下一次回收(1/100的概率)發(fā)生前,這個(gè)session仍然是有效的;

2、如果你的session使用session.save_path中使用別的地方保存session,session回收機(jī)制有可能不會(huì)自動(dòng)處理過(guò)期session文件。這時(shí)需要定時(shí)手動(dòng)(或者crontab)的刪除過(guò)期的session:cd /path/to/sessions; find -cmin +24 | xargs rm;

3、注意,當(dāng)服務(wù)器端session文件數(shù)量沒(méi)有得到有效的回收,逐漸增長(zhǎng)到gb或更大級(jí)別時(shí)可能你的站點(diǎn)在存取session時(shí)就會(huì)越來(lái)越緩慢,多見(jiàn)于站點(diǎn)登入登出會(huì)受到影響;

4、寫(xiě)日志、周報(bào)、月報(bào)等時(shí)候我們最后提交的關(guān)頭,有時(shí)會(huì)出現(xiàn)”無(wú)效的操作,請(qǐng)登陸后重試”等消息,其原因也不言而喻,可能就是session失效,gc清除那些已經(jīng)“超時(shí)”的session文件。

一些特殊情況:

因?yàn)榛厥諜C(jī)制會(huì)檢查文件的“最后修改時(shí)間”,所以如果某個(gè)會(huì)話(huà)是活躍的,但是session的內(nèi)容沒(méi)有改變過(guò),那么對(duì)應(yīng)的session文件也就沒(méi)有改變過(guò),回收機(jī)制會(huì)認(rèn)為這是一個(gè)長(zhǎng)時(shí)間沒(méi)有活躍的session而將其刪除。這是我們不愿看到的,可以通過(guò)增加如下的簡(jiǎn)單代碼解決這個(gè)問(wèn)題:

代碼如下:

<?php

if(!isset($_session['last_access'])||(time()-$_session['last_access'])>120)

$_session['last_access'] = time();

?> //代碼會(huì)每隔120秒,嘗試修改修改一次session

了解cookie與session之間的區(qū)別與聯(lián)系

相同點(diǎn):都可以在解決http無(wú)狀態(tài)的問(wèn)題,使同一個(gè)客戶(hù)端在訪問(wèn)網(wǎng)站的多次請(qǐng)求中,可以保存,設(shè)置信息,并且在請(qǐng)求事物之間建立聯(lián)系。

不同點(diǎn):簡(jiǎn)單的說(shuō)cookie的信息保存在客戶(hù)端,session的信息保存在服務(wù)器端。

session采用鍵值對(duì),也就是說(shuō)id存放客戶(hù)端,而值放在服務(wù)器端,是通過(guò)用戶(hù)的id去找服務(wù)器上對(duì)應(yīng)的值,這種方式值放置在服務(wù)器端,有個(gè)時(shí)間限制,時(shí)間到則服務(wù)器自動(dòng)回收/釋放。

cookies則有兩種方法,一種方法是把值保存在瀏覽器的變量中,當(dāng)瀏覽器關(guān)閉時(shí)結(jié)束,另一種方法是保存在硬盤(pán)中,只要時(shí)間不過(guò)期,下次還可使用。

聯(lián)系:當(dāng)客戶(hù)端使用基于cookie方式保存的sessionid時(shí),sessionid一般保存在cookie中。

備注:cookie在相同內(nèi)核的瀏覽器之間是共享的,不同內(nèi)核瀏覽器是不共享的例如火狐和ie(存放位置都不同,當(dāng)然不共享)。不同內(nèi)核瀏覽器不能共享cookie,也會(huì)產(chǎn)生不同sessionid。

問(wèn)題1:禁用cookie后session為什么會(huì)失效?

首先說(shuō)明一點(diǎn):session不一定必須依賴(lài)cookie,只是php默認(rèn)客戶(hù)端sessionid基于cookie方式保存。

到此,我想你也應(yīng)該了解了php默認(rèn)的session客戶(hù)端保存方式是基于cookie的,所以一旦客戶(hù)端禁用cookie,那么session跨頁(yè)將會(huì)失效,不知道這么描述是否合適,通俗的說(shuō)無(wú)狀態(tài)的東西要變的有狀態(tài),只能兩邊都進(jìn)行比對(duì),如果用cookie方式保存的sessionid,客戶(hù)端這邊的比對(duì)條件就放到cookie里,所以客戶(hù)端禁用cookie,session便也會(huì)隨之失效。php的session客戶(hù)端id一般有兩種保存方式:cookie和url方式。如果是cookie中保存session id,就可以看到瀏覽器的cookie中有一個(gè)phpsesid變量(可以通過(guò)firefox查看)。如果是url傳遞的(建議使用隱藏表單傳遞),就可以看到形如:index.php?phpsesid=ves0d7uvdsab9k6sig73mnn592的url。例如:

代碼如下:

demo1.php

<?php

session_start();

$_session['blog']='http://blog.jb51.net';

echo <a href='demo2.php'>test2</a>;

?>

demo2.php

<?php

session_start();

echo 'session值為'.$_session['blog'];

?>

運(yùn)行上面的代碼,在客戶(hù)端cookie正常情況下,我么可以在demo2.php中打印出$_session['blog']的值為:。但是,現(xiàn)在如果你手動(dòng)禁用客戶(hù)端的cookie,再運(yùn)行該實(shí)例,可能就得不到結(jié)果了。因?yàn)槟J(rèn)的客戶(hù)端sessionid保存方式在跨頁(yè)后,讀取不到前一頁(yè)的sessionid,當(dāng)執(zhí)行session_start();將又會(huì)產(chǎn)生一個(gè)session文件,與之對(duì)應(yīng)產(chǎn)生相應(yīng)的session id,用這個(gè)session id是取不出前面提到的第一個(gè)session文件中的變量的,因?yàn)檫@個(gè)session id不是打開(kāi)它的“鑰匙”。如果在session_start();之前加代碼session_id($sessionid);將不產(chǎn)生新的session文件,直接讀取與這個(gè)id對(duì)應(yīng)的session文件。簡(jiǎn)單的說(shuō)就是在前一頁(yè)取得session id,然后想辦法傳遞到下一頁(yè),在下一頁(yè)的session_start();代碼之前加代碼session_id(傳過(guò)來(lái)的sessionid); 例如:

代碼如下:

demo.php

<?php

$sid = $_get['sid'];

if(!empty($sid)){

session_id($sid);

session_start();

}else{

session_start();

$sid = session_id();

}

?>

<form action=demo2.php?sid=<?php echo $sid ?> method=post>

<input type=text name=id value=100 />

<input type=submit value=提交/>

</form>

demo2.php

<?php

$sid = $_get['sid'];

if(!empty($sid)){

session_id($sid);

session_start();

}else{

session_start();

$sid = session_id();

}

$id = $_post['id'];

$key = 'poll_'.$id;

if($id!=''){

echo $key = 'poll'.$id;

if(!empty($_session[$key])){

$_session[$key]=$_session[$key] + 1;

}else{

$_session[$key]=1;

setcookie($key ,$id+1,time()+3600*24);

}

echo '<script>alert(success);javascript:location.href=demo.php?sid='.$sid.';</script>';

}else{

echo '<script>alert(failed!id null);javascript:history.back(-1);</script>';

}

?>

除此之外,我們還可以將客戶(hù)端phpsesid存放到文件中,如:

代碼如下:

demo.php

session_start();

$_session['blogdomain']= 'http://blog.jb51.net';

$sid=session_id();

$fp=fopen(d:\tmp\websid.txt,w+);

fwrite($fp,$sid);

fclose($fp);

echo '<a href=demo2.php>demo2</a>';

demo2.php

$fp=fopen(d:\tmp\websid.txt,r);

$sid=fread($fp,1024);

fclose($fp);

session_id($sid);

session_start();

print_r($_session);

當(dāng)客戶(hù)端禁用cookie,可以通過(guò)以下幾種方式改變session對(duì)客戶(hù)端cookie的依賴(lài),使session拋開(kāi)客戶(hù)端cookie:

1、設(shè)置php.ini中的session.use_trans_sid = 1或者編譯時(shí)打開(kāi)打開(kāi)了--enable-trans-sid選項(xiàng),讓php自動(dòng)跨頁(yè)傳遞session id。當(dāng)session.use_trans_sid為有效時(shí),ession.use_only_cookies一定要設(shè)置為無(wú)效0。

2、手動(dòng)通過(guò)url傳值、隱藏表單傳遞session id。

3、用文件、數(shù)據(jù)庫(kù)等形式保存session_id,在跨頁(yè)過(guò)程中手動(dòng)調(diào)用。

php也提供一個(gè)函數(shù):

代碼如下:

output_add_rewrite_var ( string $name , string $value ) # 變量名 變量值

說(shuō)明:此函數(shù)給url重寫(xiě)機(jī)制添加名/值對(duì)。 這種名值對(duì)將被添加到url(以get參數(shù)的形式)和表單(以input隱藏域的形式),當(dāng)透明url重寫(xiě)用 session.use_trans_sid 開(kāi)啟時(shí)同樣可以添加到session id。 要注意,絕對(duì)url(..)不能被重寫(xiě)。此函數(shù)的行為由url_rewriter.tags php.ini 參數(shù)控制。

代碼如下:

<?

session_start();

output_add_rewrite_var('phpsessid',session_id ());

echo '<a href=demo2.php>demo</a>';

?>

這樣sessionid會(huì)跟在url后面而且from中會(huì)出現(xiàn)sessionid的hidden值。

改變session客戶(hù)端id保存方式:

session.use_cookies //控制客戶(hù)端保存sessionid時(shí)使用哪一種方式,當(dāng)它為“1”時(shí),就說(shuō)明啟動(dòng)了session cookie(初始值為1)

可以使用上面我們提到的函數(shù)來(lái)查詢(xún)得到目前的session id:echo $_cookie[phpsessid];

但是,如果client的瀏覽器不支持cookie的話(huà),即使session.use_cookies這個(gè)參數(shù)的值等于“1”,用上述的查詢(xún)也只會(huì)得到null。

php.ini中兩個(gè)和該選項(xiàng)相關(guān)的配置參數(shù):

代碼如下:

session.use_cookies = 1 //是否使用cookies(默認(rèn)值為1)

session.use_only_cookies=1 //為1時(shí)只使用cookie;為0時(shí)可使用cookie和其它方式,這時(shí)如果客戶(hù)端cookie可用,則session還是默認(rèn)用cookie(默認(rèn)值為1)

注意:如果客戶(hù)的瀏覽器是支持cookie的,強(qiáng)烈推薦“session.use_only_cookies = 1”,當(dāng)session.use_only_cookies為有效時(shí),即使想通過(guò)url來(lái)傳遞session id也會(huì)被認(rèn)為無(wú)效,這樣可以減少通過(guò)sessionid被攻擊的可能性。上面兩個(gè)配置,在php代碼頁(yè)面中設(shè)置方式:

代碼如下:

ini_set('session.use_cookies','1');

ini_set('session.use_only_cookies','1');

ie下丟失session,每次刷新頁(yè)面,都會(huì)生成新的sessionid(firefox瀏覽器都正常)

如果你的服務(wù)器或站點(diǎn)出現(xiàn)這種問(wèn)題,請(qǐng)正確配置session.cookie_path網(wǎng)站域,如果配置錯(cuò)誤可能會(huì)引起以下常見(jiàn)故障:

(1)客戶(hù)端的每個(gè)phpsessid在服務(wù)器端都會(huì)一對(duì)一的對(duì)應(yīng)生成一個(gè)獨(dú)立的session記錄存儲(chǔ)在服務(wù)器端,故服務(wù)器端session文件冗余將會(huì)增多(gc回收機(jī)制異常時(shí)、站點(diǎn)訪問(wèn)量較大時(shí))

(2)使用session記錄相關(guān)信息的站點(diǎn)可能在除firefox(chrome未測(cè)試)之外的瀏覽器下訪問(wèn)出現(xiàn)問(wèn)題,例如:購(gòu)物車(chē)無(wú)法記錄選購(gòu)項(xiàng)目、站點(diǎn)登錄失敗等

代碼如下:

session.cookie_path 是指 session 生效的網(wǎng)站域;

session.save_path 是指存儲(chǔ) session 臨時(shí)文件的路徑。

例如:session.cookie_path= / //cookie的有效路徑

補(bǔ)充:如果所有瀏覽器訪問(wèn)刷新產(chǎn)生新sessionid,請(qǐng)檢查客戶(hù)端是否禁用了cookie。

session簡(jiǎn)單實(shí)例

使用session防止表單重復(fù)提交:

代碼如下:

<?php

session_start();

$_session[num] = 0;

if(isset($_post[action] && $_post[action]==post)){

if($_session[num] == 0){

echo 提交成功!;

$_session[num] = 1;

}else{

echo 請(qǐng)勿重復(fù)提交!;

}

}

?>

使用session方式的登錄驗(yàn)證實(shí)例代碼:

代碼如下:

<?php

session_start();//啟動(dòng)session,必須放在第一句,否則會(huì)出錯(cuò)。

if($_get['out']){

unset($_session['id']);

unset($_session['pass']);

}

if($_post['name']&&$_post['password']){

<span style=font-family: 微軟雅黑;><span style=font-size: 16px;line-height:2.5em;>//用于設(shè)置session</span></span>

$_session['id']=$_post['name'];

$_session['pass']=$_post['password'];

}

if($_session['id']&&$_session['pass']){

echo 登錄成功!

用戶(hù)id:.$_session['id'].<br />用戶(hù)密碼:.$_session['pass'];

echo <br />;

echo <a href='login.php?out=out'>注銷(xiāo)session</a>;

}

?>

<form action=login.php method=post>

用戶(hù)id:<input type=text name=name />

密碼:<input type=password name=password />

<br />

<input type=submit name=submit>

</form>

使用cookie方式的登錄驗(yàn)證實(shí)例代碼:

代碼如下:

if($_get['out']){ //用于注銷(xiāo)cookies

setcookie('id',);

setcookie('pass',);

echo <script>location.href='login.php'</script>; //因?yàn)閏ookies不是及時(shí)生效的,只有你再次刷新時(shí)才生效,所以,注銷(xiāo)后讓頁(yè)面自動(dòng)刷新。

}

if($_post['name']&&$_post['password']) //如果變量用戶(hù)名和密碼存在時(shí),在下面設(shè)置cookies

{ //用于設(shè)置cookies

setcookie('id',$_post['name'],time()+3600);

setcookie('pass',$_post['password'],time()+3600);

echo <script>location.href='login.php'</script>; //讓cookies及時(shí)生效

}

if($_cookie['id']&&$_cookie['pass']){ //cookies設(shè)置成功后,用于顯示cookies

echo 登錄成功!<br />用戶(hù)名:.$_cookie['id'].

密碼:.$_cookie['pass'];

echo <br />;

echo <a href='login.php?out=out'>注銷(xiāo)cookies</a>;

}

?>

<form action= method=post>

用戶(hù)id:<input type=text name=name />

密 碼:<input type=password name=password />

<br />

<input type=submit name=submit>

</form>

使用session隨機(jī)碼驗(yàn)證投票合法性:

代碼如下:

list.php 選項(xiàng)頁(yè)面

session_start();

$tokenkey = md5(rand(1,100));

$_session['tokenkey'] = $tokenkey;

注意:在傳值時(shí)同時(shí)傳入隨機(jī)碼$tokenkey

vote.php 投票動(dòng)作執(zhí)行頁(yè)面

$tokenkey = $_session['tokenkey'];

if($_post['tokenkey'] != $tokenkey){ //判斷隨機(jī)碼是否和上一頁(yè)相同

echo <script>alert('請(qǐng)重新投票!');location.href='list.php';</script>; //隨機(jī)碼無(wú)效

exit;

}else{

執(zhí)行投票操作;

清空session存儲(chǔ)的隨機(jī)碼

}

更多信息請(qǐng)查看腳本欄目
易賢網(wǎng)手機(jī)網(wǎng)站地址:php會(huì)話(huà)控制:session與cookie詳解
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢(xún)回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門(mén)公布的正式信息和咨詢(xún)?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽(tīng)報(bào)名

  • 報(bào)班類(lèi)型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢(xún) | 簡(jiǎn)要咨詢(xún)須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專(zhuān)用圖標(biāo)
聯(lián)系電話(huà):0871-65099533/13759567129 獲取招聘考試信息及咨詢(xún)關(guān)注公眾號(hào):hfpxwx
咨詢(xún)QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專(zhuān)用圖標(biāo)