程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> PHP會話控制:Session與Cookie詳解

PHP會話控制:Session與Cookie詳解

編輯:PHP綜合

本文介紹了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'].'<br/>';
echo $_COOKIE[session_name()].'<br/>';
echo session_id().'<br/>';

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.jb51.net;
$_SESSION['poll']=$_SESSION[poll] + 1;

使用一個會話變量:
復制代碼 代碼如下:
echo $_SESSION['blogdomain'];   //打印出blog.jb51.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在相同內核的浏覽器之間是共享的,不同內核浏覽器是不共享的例如火狐和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.jb51.net';
echo "<a href='demo2.php'>test2</a>";
?>

demo2.php
<?php
session_start();
echo 'session值為'.$_SESSION['blog'];
?>

運行上面的代碼,在客戶端cookie正常情況下,我麼可以在demo2.php中打印出$_SESSION['blog']的值為:http://blog.jb51.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();
}
?>
<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);

當客戶端禁用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://jb51.net/..)不能被重寫。此函數的行為由url_rewriter.tags php.ini 參數控制。

復制代碼 代碼如下:
<?
session_start();
output_add_rewrite_var('PHPSESSID',session_id ());
echo '<a href="demo2.php">demo</a>';
?>

這樣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']){
<span style="font-family: 微軟雅黑;"><span style="font-size: 16px;line-height:2.5em;">//用於設置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方式的登錄驗證實例代碼:
復制代碼 代碼如下:
if($_GET['out']){ //用於注銷cookies
setcookie('id',"");
setcookie('pass',"");
echo "<script>location.href='login.php'</script>"; //因為cookies不是及時生效的,只有你再次刷新時才生效,所以,注銷後讓頁面自動刷新。
}
if($_POST['name']&&$_POST['password']) //如果變量用戶名和密碼存在時,在下面設置cookies
{ //用於設置cookies
setcookie('id',$_POST['name'],time()+3600);
setcookie('pass',$_POST['password'],time()+3600);
echo "<script>location.href='login.php'</script>"; //讓cookies及時生效
}
if($_COOKIE['id']&&$_COOKIE['pass']){ //cookies設置成功後,用於顯示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隨機碼驗證投票合法性:
復制代碼 代碼如下:
list.php 選項頁面
session_start();
$tokenKey = md5(rand(1,100));
$_SESSION['tokenKey'] = $tokenKey;
注意:在傳值時同時傳入隨機碼$tokenKey

vote.php  投票動作執行頁面
$tokenKey = $_SESSION['tokenKey'];
if($_POST['tokenKey'] !=  $tokenKey){     //判斷隨機碼是否和上一頁相同
  echo "<script>alert('請重新投票!');location.href='list.php';</script>";   //隨機碼無效
  exit;
}else{
  執行投票操作;
  清空session存儲的隨機碼
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved