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

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

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

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

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

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

• 問題1:禁用cookie后session為什么會失效?

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

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

理解會話控制的概念

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

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

由此我們就會覺得很奇怪了,平時(shí)我們在論壇逛帖子或電商網(wǎng)站購物時(shí),只要我們在這個(gè)站點(diǎn)內(nèi),不論我們怎么跳轉(zhuǎn),從一個(gè)頁面跑到另一個(gè)頁面,網(wǎng)站總會記得我是誰,比如告訴你購買了哪些東西。這是怎么做到的呢,估計(jì)大家猜到了,這就是運(yùn)用了http會話控制。在網(wǎng)站中跟蹤一個(gè)變量,通過對變量的跟蹤,使多個(gè)請求事物之間建立聯(lián)系,根據(jù)授權(quán)和用戶身份顯示不同的內(nèi)容、不同頁面。

php session會話控制:

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

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

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

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

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

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

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

文件:cookie:administrator@localhost/

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

cookie的創(chuàng)建:

代碼如下:

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

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

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

cookie的維護(hù):

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

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

cookie失效時(shí)間:

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

代碼如下:

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

setcookie(vote,$id);

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

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

cookie自動(dòng)刪除:

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

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

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

代碼如下:

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

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

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

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

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

session的創(chuàng)建:

代碼如下:

session_start() //開始一個(gè)會話及返回已經(jīng)存在會話

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

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

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

session id:

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

獲得session_id():

代碼如下:

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

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

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

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

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

注冊一個(gè)會話變量:

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

代碼如下:

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

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

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

代碼如下:

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

注銷session變量/銷毀會話:

代碼如下:

unset($_session); //銷毀單個(gè)會話變量

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

#unset($_session)這個(gè)函數(shù)會將全局變量$_session銷毀,而且還沒有可行的辦法將其恢復(fù)。用戶也不再可以注冊$_session變量,所以此函數(shù)千萬不可使用。

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

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

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

session_destroy();

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

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

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

備注:

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

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

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

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

我們把初始化session開始,直到注銷session這段期間,稱為session生命周期

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

代碼如下:

poll_200|i:1;poll_100|i:3; //#變量名|類型:長度:值

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

php session是基于cookie的,所以要設(shè)置session的生命周期,首先要設(shè)置cookie的失效時(shí)間。因?yàn)樵诳蛻舳耍ㄈ鐬g覽器)登錄網(wǎng)站時(shí),session 是否有用,首先找客戶端是否有 cookie,通過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(); 來設(shè)置php5 session的生存期的,該函數(shù)必須在 session_start() 函數(shù)調(diào)用之前調(diào)用:

代碼如下:

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

session_set_cookie_params($lifetime);

session_start();

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

代碼如下:

session.gc_maxlifetime = 1440 (初始值)

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

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

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

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

代碼如下:

session.gc_probability = 1 (初始值)

session.gc_divisor = 100 (初始值)

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

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

補(bǔ)充說明:

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

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

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

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

一些特殊情況:

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

代碼如下:

<?php

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

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

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

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

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

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

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

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

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

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

問題1:禁用cookie后session為什么會失效?

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

到此,我想你也應(yīng)該了解了php默認(rèn)的session客戶端保存方式是基于cookie的,所以一旦客戶端禁用cookie,那么session跨頁將會失效,不知道這么描述是否合適,通俗的說無狀態(tài)的東西要變的有狀態(tài),只能兩邊都進(jìn)行比對,如果用cookie方式保存的sessionid,客戶端這邊的比對條件就放到cookie里,所以客戶端禁用cookie,session便也會隨之失效。php的session客戶端id一般有兩種保存方式:cookie和url方式。如果是cookie中保存session id,就可以看到瀏覽器的cookie中有一個(gè)phpsesid變量(可以通過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)行上面的代碼,在客戶端cookie正常情況下,我么可以在demo2.php中打印出$_session['blog']的值為:。但是,現(xiàn)在如果你手動(dòng)禁用客戶端的cookie,再運(yùn)行該實(shí)例,可能就得不到結(jié)果了。因?yàn)槟J(rèn)的客戶端sessionid保存方式在跨頁后,讀取不到前一頁的sessionid,當(dāng)執(zhí)行session_start();將又會產(chǎn)生一個(gè)session文件,與之對應(yīng)產(chǎn)生相應(yīng)的session id,用這個(gè)session id是取不出前面提到的第一個(gè)session文件中的變量的,因?yàn)檫@個(gè)session id不是打開它的“鑰匙”。如果在session_start();之前加代碼session_id($sessionid);將不產(chǎn)生新的session文件,直接讀取與這個(gè)id對應(yīng)的session文件。簡單的說就是在前一頁取得session id,然后想辦法傳遞到下一頁,在下一頁的session_start();代碼之前加代碼session_id(傳過來的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>';

}

?>

除此之外,我們還可以將客戶端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)客戶端禁用cookie,可以通過以下幾種方式改變session對客戶端cookie的依賴,使session拋開客戶端cookie:

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

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

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

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

代碼如下:

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

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

代碼如下:

<?

session_start();

output_add_rewrite_var('phpsessid',session_id ());

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

?>

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

改變session客戶端id保存方式:

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

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

但是,如果client的瀏覽器不支持cookie的話,即使session.use_cookies這個(gè)參數(shù)的值等于“1”,用上述的查詢也只會得到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í)如果客戶端cookie可用,則session還是默認(rèn)用cookie(默認(rèn)值為1)

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

代碼如下:

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

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

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

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

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

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

代碼如下:

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

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

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

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

session簡單實(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 請勿重復(fù)提交!;

}

}

?>

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

代碼如下:

<?php

session_start();//啟動(dòng)session,必須放在第一句,否則會出錯(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 登錄成功!

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

echo <br />;

echo <a href='login.php?out=out'>注銷session</a>;

}

?>

<form action=login.php method=post>

用戶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']){ //用于注銷cookies

setcookie('id',);

setcookie('pass',);

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

}

if($_post['name']&&$_post['password']) //如果變量用戶名和密碼存在時(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 />用戶名:.$_cookie['id'].

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

echo <br />;

echo <a href='login.php?out=out'>注銷cookies</a>;

}

?>

<form action= method=post>

用戶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)頁面

session_start();

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

$_session['tokenkey'] = $tokenkey;

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

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

$tokenkey = $_session['tokenkey'];

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

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

exit;

}else{

執(zhí)行投票操作;

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

}

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

2025國考·省考課程試聽報(bào)名

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