本文介紹了PHP會話控制,主要闡述以下幾點內容:
• 會話控制的產生背景/概念
• cookie的維護與生命週期(有效時間)
• session的維護與生命週期(回收機制)
• cookie與session之間的區別與聯絡
• 問題1:禁用cookie後session為什麼會失效?
• 問題2:IE瀏覽器下丟失session,每次重新整理頁面,都會產生新的sessionID(Firefox瀏覽器正常)
• session、cookie簡單一實例
理解會話控制的概念
理解一個概念就需要理解他的背景及產生的原因,這裡引入WEB環境及其HTTP協議。會話控制產生的背景:
閱讀過HTTP協議相關資料的同學都會知道HTTP協議是WEB伺服器與用戶端(瀏覽器)相互連信的協議,它是一種無狀態協議,所謂無狀態,指的是不會維護http請求資料,http請求是獨立的,不持久的。也就是說HTTP協議沒有一個內建的機制來維護兩個事務之間的狀態或者說是關係吧。當一個使用者在請求一個頁面後再去請求另外一個頁面時,HTTP將無法告訴我們這兩個請求是否來自同一個使用者。
由此我們就會覺得很奇怪了,平時我們在論壇逛文章或電商網站購物時,只要我們在這個網站內,不論我們怎麼跳轉,從一個頁面跑到另一個頁面,網站總會記得我是誰,比如告訴你購買了哪些東西。這是怎麼做到的呢,估計大家猜到了,這就是運用了HTTP會話控制。在網站中跟蹤一個變數,通過對變數的跟蹤,使多個請求事物之間建立聯絡,根據授權和使用者身份顯示不同的內容、不同頁面。
PHP Session會話控制:
PHP的session會話是通過唯一的會話ID來驅動的,會話ID是一個加密的隨機數字,由PHP產生,在會話的生命週期中都會儲存在用戶端。我們知道用戶端(也就是瀏覽器)儲存資料的地方只有cookie,所以PHP的會話ID一般儲存在使用者機器的cookie中。瞭解cookie後我們知道,瀏覽器是可以禁用cookie的,這樣會話就會失效。所以PHP會話控制還有一種模式,就是在URL中傳遞會話ID。如果在瀏覽網站時我們稍加留心的話,有些URL中有一串看起來像隨機數位字串,那麼其實很有可能就是URL形式的會話控制。
講到這裡,有些人可能會有疑問了,用戶端只是儲存一個會話ID,那麼會話控制中儲存的會話變數比如你購物時買的物品列表等,它們是存放在哪個地方的呢?很顯然,會話變數是在伺服器端使用的,那麼這些會話變數必定存放在伺服器端。預設情況下,會話變數儲存在伺服器的普通檔案中(也可以自己配置使用資料庫來儲存,可以Google一下),會話ID的作用就像是一把鑰匙,在伺服器端儲存會話的檔案中找到該會話ID對應的會話變數,比如購買物品的列表。
那麼會話控制的整個過程可能就像這個樣子,使用者登入或者第一次瀏覽某個網站的頁面時,該網站會產生一個PHP的會話ID並通過cookie發送到用戶端(瀏覽器)。當使用者點擊該網站的另一個頁面時,瀏覽器開始串連這個URL。在串連之前,瀏覽器會先搜尋本地儲存的cookie,如果在cookie中有任何與正在串連的URL相關的cookie,就將它提交到伺服器。而剛好在登陸或第一次串連時,已經產生了一個與該網站URL相關的cookie(儲存的會話ID),所以當使用者再次串連這個網站時,網站就可以通過這個會話ID識別出使用者,從伺服器的會話檔案中取出與這個會話ID相關的會話變數,從而保持事務之間的連續。
接下來我們瞭解下兩個重要的概念:cookie和session
關於cookie的維護與生命週期
cookie是在伺服器端被建立並寫回到用戶端瀏覽器,瀏覽器接到回應標頭中關於寫cookie的指令則在本地臨時檔案夾中。
建立了一個cookie檔案,其中儲存了你的cookie內容,cookie內容的儲存是索引值對的方式,鍵和值都只能是字串。例如:
檔案:Cookie:administrator@localhost/
內容格式:voteID100101localhost/15361167667230343893360385046430343691*
cookie的建立:
複製代碼 代碼如下:
setcookie()函數設定cookie,函數原型如下
setcookie(name, value, expire, path, domain);
注釋:cookie標題頭必須在發送其他標題頭之前發送,否則就無效(這是cookie的限制,而不是PHP的限制)。在發送 cookie 時,cookie 的值會自動進行 URL 編碼,在取回時進行自動解碼(為防止 URL 編碼,請使用 setrawcookie() 取而代之)。
cookie的維護:
cooke有四個標識符:cookie的name,domain,path,secure標記。要想在將來改變這個cookie的值,需要發送另一個具有相同cookie name,domain,path的Set-Cookie訊息頭,這將以一個新
的值來覆蓋原來cookie的值。然而,如果僅僅只是改變這些選項的某一個也會建立一個完全不同的cookie,如只是更改了name值。
cookie失效時間:
可以設定到期時間,如果不設定則是會話層級的,即關閉瀏覽器就會消失。當cookie建立時包含了失效日期,這個失效日期則關聯了以name-domain-path-secure為標識的cookie。要改變一個cookie的失效日期,你必須指定同樣的組合。當改變一個cookie的值時,你不必每次都設定失效日期,因為它不是cookie標識資訊的組成部分。例如:
複製代碼 代碼如下:
setcookie(vote ,$id+1,time()+3600*24);
setcookie(vote,$id);
在cookie上的失效日期並沒有改變,因為cookie的標識符是相同的。實際上,只有你手工的改變cookie的失效日期,否則其失效日期不會改變。這意味著在同一個會話中,一個會話cookie可以變成一個持久化cookie(一個可以在多個會話中存在的),反之則不可。為了要將一個持久化cookie變為一個會話cookie,你必須刪除這個持久化cookie,這隻要設定它的失效日期為過去某個時間之後再建立一個同名的會話cookie就可以實現。
需要記得的是失效日期是以瀏覽器啟動並執行電腦上的系統時間為基準進行核實的。沒有任何辦法來來驗證這個系統時間是否和伺服器的時間同步,所以當伺服器時間和瀏覽器所處系統時間存在差異時這樣的設定會出現錯誤。
cookie自動刪除:
cookie會被瀏覽器自動刪除,通常存在以下幾種原因:
會話cooke(Session cookie)在會話結束時(瀏覽器關閉)會被刪除
持久化cookie(Persistent cookie)在到達失效日期時會被刪除,如:
複製代碼 代碼如下:
setcookie("vote", "", time()-3600);
如果瀏覽器中的cookie限制到達,那麼cookies會被刪除以為建立cookies建立空間。
關於session的維護與生命週期
Session是由應用伺服器維持的一個伺服器端的儲存空間,使用者在串連伺服器時,會由伺服器建立產生一個唯一的sessionID,用該sessionID為標識符來存取伺服器端的Session儲存空間,在會話期間,分配給用戶端的唯一sessionID,用來標識目前使用者,與其他使用者進行區分。通過SessionID接受每一次訪問的請求,從而識別目前使用者,跟蹤和保持使用者的具體資料,以及session變數,可在session中儲存數字或文字資料.比如session_name.這些資訊都儲存在伺服器端。當然,sessionID也可以作為會話資訊儲存到資料庫中,進行session持久化。這樣可以跟蹤使用者的登陸次數、線上與否、線上時間等從而維護HTTP無狀態事物之間的關係。session的內容儲存是索引值對的列表,鍵是字串類型,session的儲存更方便,值可以是對象。
在session會話期間,session會分別儲存在用戶端和伺服器端兩個檔案,用戶端可以是cookie方式儲存的sessionID(預設的儲存方式)或通過url字串形式傳遞。伺服器端一般以文本的形式儲存在指定的session目錄中。在伺服器端我們可以通過session.use_cookies來控制用戶端使用哪一種儲存方式。如果定義為cookie儲存方式,我們可以通過session.cookie_lifetime(預設值0,閉瀏覽器就清除)來控制被儲存在client上的cookie的有效期間。而如果用戶端用cookie方式儲存的sessionID,則使用“臨時”的cookie儲存(cookie的名稱為PHPSESSID,通過Firebug你可以瞭解到詳細的資訊,該名稱你可以通過php.ini session.name變更),使用者提交頁面時,會將這一SessionID提交到伺服器端,來存取session資料。這一過程,是不用開發人員幹預的。
Session的建立:
複製代碼 代碼如下:
session_start() //開始一個會話及返回已經存在會話
功能:初始化Session,也標識著session生命週期的開始。要使用session,必須初始化一個session環境,有點類似於OOP概念中調用建構函式構建立對象執行個體一樣。session初始化操作,聲明一個全域數組$_SESSION,映射寄存在記憶體的session資料。如果session檔案已經存在,並且儲存有session資料,session_start()則會讀取session資料,填入$_SESSION中,開始一個新的session生命週期。
說明:這個函數沒有參數,且傳回值為true,如果使用基於cookie的sessin,那麼在session_satrt()之前不能有任何的輸出,包括空白
如果在php.ini中session.auto_start=1開啟,則在每個頁面執行session_start(),不需要手工設定,該選項預設為關閉狀態,開啟後不能將對象放入session中。
Session ID:
使用者session唯一識別碼,隨機產生的一串字串,具有唯一性,隨機性。主要用於區分其它使用者的session資料。使用者第一次訪問web頁面的時候,php的session初始化函數調用會分配給當前來訪使用者一個唯一的ID,也稱之為session_id。
獲得session_id():
複製代碼 代碼如下:
echo $_COOKIE['PHPSESSID'].'
';
echo $_COOKIE[session_name()].'
';
echo session_id().'
';
session資料:
我們把需要通過session儲存的使用者狀態資訊,稱為使用者session資料,也稱為session data。一般是在當前session生命週期內,相應的$_SESSION資料。一旦調用了session_start()初始化session,就意味著開始了一個session生命週期。也就是宣布了,可以使用相關函數操作$_SESSION來管理session資料。這個session生命週期產生的資料並沒有即時地寫入session檔案,而是通過$_SESSION變數寄存在記憶體中。$_SESSION是一個全域變數,類型是Array,映射了session生命週期的session資料,寄存在記憶體中。在session初始化的時候,從session檔案中讀取資料,填入該變數中。在session(生命週期)結束時,將$_SESSION資料寫回session檔案。
註冊一個會話變數:
從PHP4.1以後,會話變數儲存在超級全域數組$_SESSION中。要建立一會話變數,只需要在數組中設定一個元素,如:
複製代碼 代碼如下:
$_SESSION['domain'] = blog.php.net;
$_SESSION['poll']=$_SESSION[poll] + 1;
使用一個會話變數:
複製代碼 代碼如下:
echo $_SESSION['blogdomain']; //列印出blog.php.net,使用會話前必須先使用session_start()函數啟動一個會話
登出Session變數/銷毀會話:
複製代碼 代碼如下:
unset($_SESSION); //銷毀單個會話變數
如:unset($_SESSION['blogdomain']);
#unset($_SESSION)這個函數會將全域變數$_SESSION銷毀,而且還沒有可行的辦法將其恢複。使用者也不再可以註冊$_SESSION變數,所以此函數千萬不可使用。
session_unset(); //多項釋放。將所有登陸在session檔案裡的變數釋放出來
#在session生命週期,從當前session中登出全部session資料,讓$_SESSION成為一個空數組。它與unset($_SESSION)的區別在於:unset直接刪除$_SESSION變數,釋放記憶體資源;另一個區別在於,session_unset()僅在session生命週期能夠操作$_SESSION數組,而unset()則在整個頁面(page)生命週期都能操作$_SESSION數組。session_unset()同樣不進行任何IO操作,隻影響$_SESSION數組。
$_SESSION=array(); //多項釋放,釋放所有登入在$_SESSION參數裡的變數
session_destroy();
#當使用完一個會話後,首先應該登出所有的變數,然後再調用該函數結束當前的會話,並清空會話中的所有資源,刪除伺服器上的session檔案.該函數不會unset(釋放)和當前session相關的全域變數,也不會刪除用戶端的session cookie
#如果說session_start()初始化一個session的話,而它則登出一個session。意味著session生命週期結束了。在session生命週期結整後, session_unset, $_SESSION['domain'] 都將不能操作$_SESSION數組,而$_SESSION數組依然可以被unset()等函數操作。這時,session意味著是未定義的,而$_SESSION依然是一個全域變數,他們脫離了關映射關係。
通過session_destroy()登出session,除了結束session生命週期外,它還會刪除sesion檔案,但不會影響當前$_SESSION變數。即它會產生一個IO操作。
備忘:
1、php預設的session是基於cookie的,如果要刪除cookie的話,必須藉助setcookie()函數
2、session_unset()和unset()函數區別:
在session生命週期,session_unset()從當前session中登出全部session資料,讓$_SESSION成為一個空數組。它與unset($_SESSION)的區別在於:unset直接刪除$_SESSION變數,釋放記憶體資源;另一個區別在於,session_unset()僅在session生命週期能夠操作$_SESSION數組,而unset()則在整個頁面(page)生命週期都能操作$_SESSION數組。session_unset()同樣不進行任何IO操作,隻影響$_SESSION數組。
Session生命週期(session lifetime):Session失效時間與到期回收機制
我們把初始化session開始,直到登出session這段期間,稱為session生命週期
預設的,php會將session儲存在php.ini配置中session.save_path設定的目錄下,檔案名稱為這個樣子:sess_ves0d7uvdsab9k6sig73mnn592。每一個檔案對應了一個session(會話)。session檔案格式大致如下:
複製代碼 代碼如下:
poll_200|i:1;poll_100|i:3; //#變數名|類型:長度:值
設定SESSION的生命週期:
php session是基於cookie的,所以要設定session的生命週期,首先要設定cookie的失效時間。因為在用戶端(如瀏覽器)登入網站時,SESSION 是否有用,首先找用戶端是否有 COOKIE,通過COOKIE 中的 SESSION ID 去找伺服器上的檔案。
複製代碼 代碼如下:
session_start();
$lifeTime = 24 * 3600; // 儲存一天
setcookie(session_name(), session_id(), time() + $lifeTime, "/");
其實PHP5 Session還提供了一個函數 session_set_cookie_params(); 來設定PHP5 Session的生存期的,該函數必須在 session_start() 函數調用之前調用:
複製代碼 代碼如下:
$lifeTime = 24 * 3600; // 儲存一天
session_set_cookie_params($lifeTime);
session_start();
在伺服器端,php如何判斷session檔案是否到期?
複製代碼 代碼如下:
session.gc_maxlifetime = 1440 (初始值)
#設定session存活時間,單位是秒。每次GC啟動後, 會通過stat得到session檔案最後訪問的unix時間,通過現在時間減去檔案最後訪問時間之間大於session.gc_maxlifetime,則會刪除該檔案。
如果"最後的修改時間"到"現在"超過了session.gc_maxlifetime(預設是1440)秒,也就是說在這裡設定的時間內,該檔案沒有被修改過,這個session檔案就被認為是到期了,由於php5的session採用被動的回收機制,到期的session檔案不會自己消失,而是通過觸發“回收”來處理到期的session,那麼在下一次session回收的時候,如果這個檔案仍然沒有被更改過,這個session檔案就會被刪除(session就到期了)。
session回收何時發生?
預設情況下,每一次php請求,就會有1%的機率發生回收,所以可能簡單的理解為“每100次php請求就可能有一次回收機率發生”。這個機率是通過以下參數控制的:
複製代碼 代碼如下:
session.gc_probability = 1 (初始值)
session.gc_divisor = 100 (初始值)
#由這二個函數決定了啟用GC的機率,預設是1/1000。也就是說,每一千次使用者請求中有一次會啟動GC回收session。啟動GC進程不宜過於頻繁。過於頻繁訪問的網站,並發量大的網站,可減小PHP GC的啟動頻率。PHP GC回收session會降低php的執行效率。
這兩個合起來就是啟動Gabadge Collection(gc)進程管理機率的,在session初使化時(session_start())。Gabadge Collection啟動後跟蹤session資訊檔。其啟動機率為session.gc_probability/session.gc_divisor。也就是說不是每個session資訊檔都有100%的被系統當作垃圾來處理的。如果直接關閉瀏覽器的話,session資訊檔很多情況下都是留在了伺服器上,如果把機率改成了100%,雖然Gabadge Collection百分之百被啟動了,但是這會對伺服器添加負荷,也就失去了GC本身的意義了。
補充說明:
1、假設這種情況session.gc_maxlifetime=1440,如果某個session檔案最後修改時間是1440秒之前,那麼在下一次回收(1/100的機率)發生前,這個session仍然是有效;
2、如果你的session使用session.save_path中使用別的地方儲存session,session回收機制有可能不會自動處理到期session檔案。這時需要定時手動(或者crontab)的刪除到期的session:cd /path/to/sessions; find -cmin +24 | xargs rm;
3、注意,當伺服器端session檔案數量沒有得到有效回收,逐漸增長到GB或更大層級時可能你的網站在存取session時就會越來越緩慢,多見於網站登入登出會受到影響;
4、寫日誌、周報、月報等時候我們最後提交的關頭,有時會出現”無效的操作,請登陸後重試”等訊息,其原因也不言而喻,可能就是session失效,gc清除那些已經“逾時”的session檔案。
一些特殊情況:
因為回收機制會檢查檔案的“最後修改時間”,所以如果某個會話是活躍的,但是session的內容沒有改變過,那麼對應的session檔案也就沒有改變過,回收機制會認為這是一個長時間沒有活躍的session而將其刪除。這是我們不願看到的,可以通過增加如下的簡單代碼解決這個問題:
複製代碼 代碼如下:
<?php
if(!isset($_SESSION['last_access'])||(time()-$_SESSION['last_access'])>120)
$_SESSION['last_access'] = time();
?> //代碼會每隔120秒,嘗試修改修改一次session
瞭解cookie與session之間的區別與聯絡
相同點:都可以在解決HTTP無狀態的問題,使同一個用戶端在訪問網站的多次請求中,可以儲存,設定資訊,並且在請求事物之間建立聯絡。
不同點:簡單的說cookie的資訊儲存在用戶端,session的資訊儲存在伺服器端。
Session採用索引值對,也就是說ID存放用戶端,而值放在伺服器端,是通過使用者的ID去找伺服器上對應的值,這種方式值放置在伺服器端,有個時間限制,時間到則伺服器自動回收/釋放。
Cookies則有兩種方法,一種方法是把值儲存在瀏覽器的變數中,當瀏覽器關閉時結束,另一種方法是儲存在硬碟中,只要時間不到期,下次還可使用。
聯絡:當用戶端使用基於Cookie方式儲存的SessionID時,SessionID一般儲存在cookie中。
備忘:cookie在相同核心的瀏覽器之間是共用的,不同核心瀏覽器是不共用的例如Firefox和IE(存放位置都不同,當然不共用)。不同核心瀏覽器不能共用cookie,也會產生不同sessionid。
問題1:禁用cookie後session為什麼會失效?
首先說明一點:session不一定必須依賴cookie,只是php預設用戶端sessionid基於cookie方式儲存。
到此,我想你也應該瞭解了php預設的session用戶端儲存方式是基於cookie的,所以一旦用戶端禁用Cookie,那麼session跨頁將會失效,不知道這麼描述是否合適,通俗的說無狀態的東西要變的有狀態,只能兩邊都進行比對,如果用cookie方式儲存的SessionID,用戶端這邊的比對條件就放到cookie裡,所以用戶端禁用cookie,session便也會隨之失效。php的session用戶端ID一般有兩種儲存方式:cookie和url方式。如果是cookie中儲存session ID,就可以看到瀏覽器的cookie中有一個PHPSESID變數(可以通過firefox查看)。如果是URL傳遞的(建議使用隱藏表單傳遞),就可以看到形如:index.php?PHPSESID=ves0d7uvdsab9k6sig73mnn592的URL。例如:
複製代碼 代碼如下:
demo1.php
<?php
session_start();
$_SESSION['blog']='http://blog.php.net';
echo "test2";
?>
demo2.php
<?php
session_start();
echo 'session值為'.$_SESSION['blog'];
?>
運行上面的代碼,在用戶端cookie正常情況下,我麼可以在demo2.php中列印出$_SESSION['blog']的值為:http://blog.php.net。但是,現在如果你手動禁用用戶端的cookie,再運行該執行個體,可能就得不到結果了。因為預設的用戶端sessionid儲存方式在跨頁後,讀取不到前一頁的sessionid,當執行session_start();將又會產生一個session檔案,與之對應產生相應的session id,用這個session id是取不出前面提到的第一個session檔案中的變數的,因為這個session id不是開啟它的“鑰匙”。如果在session_start();之前加代碼session_id($sessionid);將不產生新的session檔案,直接讀取與這個id對應的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();
}
?>
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 '';
}else{
echo '';
}
?>
除此之外,我們還可以將用戶端PHPSESID存放到檔案中,如:
複製代碼 代碼如下:
demo.php
session_start();
$_SESSION['blogdomain']= 'http://blog.php.net';
$sid=session_id();
$fp=fopen("D:\tmp\websid.txt","w+");
fwrite($fp,$sid);
fclose($fp);
echo 'demo2';
demo2.php
$fp=fopen("D:\tmp\websid.txt","r");
$sid=fread($fp,1024);
fclose($fp);
session_id($sid);
session_start();
print_r($_SESSION);
當用戶端禁用cookie,可以通過以下幾種方式改變session對用戶端cookie的依賴,使session拋開用戶端cookie:
1、設定php.ini中的session.use_trans_sid = 1或者編譯時間開啟開啟了--enable-trans-sid選項,讓PHP自動跨頁傳遞session id。當session.use_trans_sid為有效時,ession.use_only_cookies一定要設定為無效0。
2、手動通過URL傳值、隱藏表單傳遞session id。
3、用檔案、資料庫等形式儲存session_id,在跨頁過程中手動調用。
PHP也提供一個函數:
複製代碼 代碼如下:
output_add_rewrite_var ( string $name , string $value ) # 變數名 變數值
說明:此函數給URL重寫機制添加名/值對。 這種名值對將被添加到URL(以GET參數的形式)和表單(以input隱藏欄位的形式),當透明URL重寫用 session.use_trans_sid 開啟時同樣可以添加到session ID。 要注意,絕對URL(http://php.net/..)不能被重寫。此函數的行為由url_rewriter.tags php.ini 參數控制。
複製代碼 代碼如下:
<?
session_start();
output_add_rewrite_var('PHPSESSID',session_id ());
echo 'demo';
?>
這樣sessionID會跟在URL後面而且from中會出現sessionID的hidden值。
改變session用戶端ID儲存方式:
session.use_cookies //控制用戶端儲存SessionID時使用哪一種方式,當它為“1”時,就說明啟動了session cookie(初始值為1)
可以使用上面我們提到的函數來查詢得到目前的session id:echo $_COOKIE["PHPSESSID"];
但是,如果client的瀏覽器不支援cookie的話,即使session.use_cookies這個參數的值等於“1”,用上述的查詢也只會得到null。
php.ini中兩個和該選項相關的配置參數:
複製代碼 代碼如下:
session.use_cookies = 1 //是否使用cookies(預設值為1)
session.use_only_cookies=1 //為1時只使用cookie;為0時可使用cookie和其它方式,這時如果用戶端cookie可用,則session還是預設用cookie(預設值為1)
注意:如果客戶的瀏覽器是支援cookie的,強烈推薦“session.use_only_cookies = 1”,當session.use_only_cookies為有效時,即使想通過URL來傳遞session id也會被認為無效,這樣可以減少通過sessionid被攻擊的可能性。上面兩個配置,在php字碼頁面中設定方式:
複製代碼 代碼如下:
ini_set('session.use_cookies','1');
ini_set('session.use_only_cookies','1');
IE下丟失session,每次重新整理頁面,都會產生新的sessionID(Firefox瀏覽器都正常)
如果你的伺服器或網站出現這種問題,請正確配置session.cookie_path網站域,如果配置錯誤可能會引起以下常見故障:
(1)用戶端的每個PHPSESSID在伺服器端都會一對一的對應產生一個獨立的session記錄儲存在伺服器端,故伺服器端session檔案冗餘將會增多(GC回收機制異常時、網站訪問量較大時)
(2)使用session記錄相關資訊的網站可能在除Firefox(Chrome未測試)之外的瀏覽器下訪問出現問題,例如:購物車無法記錄選購項目、網站登入失敗等
複製代碼 代碼如下:
session.cookie_path 是指 session 生效的網站域;
session.save_path 是指儲存 session 臨時檔案的路徑。
例如:session.cookie_path= / //cookie的有效路徑
補充:如果所有瀏覽器訪問重新整理產生新sessionID,請檢查用戶端是否禁用了cookie。
session簡單一實例
使用session防止表單重複提交:
複製代碼 代碼如下:
<?php
session_start();
$_SESSION["num"] = 0;
if(isset($_POST["action"] && $_POST["action"]=="post")){
if($_SESSION["num"] == 0){
echo "提交成功!";
$_SESSION["num"] = 1;
}else{
echo "請勿重複提交!";
}
}
?>
使用session方式的登入驗證執行個體代碼:
複製代碼 代碼如下:
<?php
session_start();//啟動session,必須放在第一句,否則會出錯。
if($_GET['out']){
unset($_SESSION['id']);
unset($_SESSION['pass']);
}
if($_POST['name']&&$_POST['password']){
//用於設定session
$_SESSION['id']=$_POST['name'];
$_SESSION['pass']=$_POST['password'];
}
if($_SESSION['id']&&$_SESSION['pass']){
echo "登入成功!
使用者ID:".$_SESSION['id']."
使用者密碼:".$_SESSION['pass'];
echo "
";
echo "登出session";
}
?>
使用cookie方式的登入驗證執行個體代碼:
複製代碼 代碼如下:
if($_GET['out']){ //用於登出cookies
setcookie('id',"");
setcookie('pass',"");
echo ""; //因為cookies不是及時生效的,只有你再次重新整理時才生效,所以,登出後讓頁面自動重新整理。
}
if($_POST['name']&&$_POST['password']) //如果變數使用者名稱和密碼存在時,在下面設定cookies
{ //用於設定cookies
setcookie('id',$_POST['name'],time()+3600);
setcookie('pass',$_POST['password'],time()+3600);
echo ""; //讓cookies及時生效
}
if($_COOKIE['id']&&$_COOKIE['pass']){ //cookies設定成功後,用於顯示cookies
echo "登入成功!
使用者名稱:".$_COOKIE['id']."
密碼:".$_COOKIE['pass'];
echo "
";
echo "登出cookies";
}
?>
使用session隨機碼驗證投票合法性:
複製代碼 代碼如下:
list.php 選項頁面
session_start();
$tokenKey = md5(rand(1,100));
$_SESSION['tokenKey'] = $tokenKey;
注意:在傳值時同時傳入隨機碼$tokenKey
vote.php 投票動作執行頁面
$tokenKey = $_SESSION['tokenKey'];
if($_POST['tokenKey'] != $tokenKey){ //判斷隨機碼是否和上一頁相同
echo ""; //隨機碼無效
exit;
}else{
執行投票操作;
清空session儲存的隨機碼
}