1. 程式人生 > >PHP中Cookie與Session的異同以及使用

PHP中Cookie與Session的異同以及使用

重寫 不容易 包含 ron pat 指示 修改表 持久 pri

Cookie與Session的異同:

一、cookie機制

Cookies是服務器在本地機器上存儲的小段文本並隨每一個請求發送至同一個服務器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie規範。網絡服務器用HTTP頭向客戶端發送cookies,在客戶終端,瀏覽器解析這些cookies並將它們保存為一個本地文件,它會自動將同一服務器的任何請求縛上這些cookies 。

具體來說cookie機制采用的是在客戶端保持狀態的方案。它是在用戶端的會話狀態的存貯機制,他需要用戶打開客戶端的cookie支持。cookie的作用就是為了解決HTTP協議無狀態的缺陷所作的努力。
正統的cookie分發是通過擴展HTTP協議來實現的,服務器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript也可以生成cookie。而cookie的使用是由瀏覽器按照一定的原則在後臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。

cookie的內容主要包括:名字,值,過期時間,路徑。路徑與域一起構成cookie的作用範圍。若不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,關閉瀏覽器窗口,cookie就消失。這種生命期為瀏覽器會話期的cookie被稱為會話cookie。會話cookie一般不存儲在硬盤上而是保存在內存裏,當然這種行為並不是規範規定的。若設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。存儲在硬盤上的cookie可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對於保存在內存裏的cookie,不同的瀏覽器有不同的處理方式。

而session機制采用的是一種在服務器端保持狀態的解決方案。同時我們也看到,由於采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助於cookie機制來達到保存標識的目的。而session提供了方便管理全局變量的方式 。

session是針對每一個用戶的,變量的值保存在服務器上,用一個sessionID來區分是哪個用戶session變量,這個值是通過用戶的瀏覽器在訪問的時候返回給服務器,當客戶禁用cookie時,這個值也可能設置為由get來返回給服務器。

就安全性來說:當你訪問一個使用session 的站點,同時在自己機子上建立一個cookie,建議在服務器端的session機制更安全些,因為它不會任意讀取客戶存儲的信息。

二、session機制

session機制是一種服務器端的機制,服務器使用一種類似於散列表的結構(也可能就是使用散列表)來保存信息。

當程序需要為某個客戶端的請求創建一個session時,服務器首先檢查這個客戶端的請求裏是否已包含了一個session標識(稱為session id),如果已包含則說明以前已經為此客戶端創建過session,服務器就按照session id把這個session檢索出來使用(檢索不到,會新建一個),如果客戶端請求不包含session id,則為此客戶端創建一個session並且生成一個與此session相關聯的session id,session id的值應該是一個既不會重復,又不容易被找到規律以仿造的字符串,這個session id將被在本次響應中返回給客戶端保存。

保存這個session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發揮給服務器。一般這個cookie的名字都是類似於SEEESIONID。但cookie可以被人為的禁止,則必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回服務器。
經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的後面。還有一種技術叫做表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session id傳遞回服務器。

Cookie與Session都能夠進行會話跟蹤,但是完成的原理不太一樣。普通狀況下二者均能夠滿足需求,但有時分不能夠運用Cookie,有時分不能夠運用Session。

下面經過比擬闡明二者的特性以及適用的場所。

1 .存取方式的不同

Cookie中只能保管ASCII字符串,假如需求存取Unicode字符或者二進制數據,需求先進行編碼。Cookie中也不能直接存取Java對象。若要存儲略微復雜的信息,運用Cookie是比擬艱難的。
而Session中能夠存取任何類型的數據,包括而不限於String、Integer、List、Map等。Session中也能夠直接保管Java Bean乃至任何Java類,對象等,運用起來十分便當。能夠把Session看做是一個Java容器類。

2 .隱私策略的不同

Cookie存儲在客戶端閱讀器中,對客戶端是可見的,客戶端的一些程序可能會窺探、復制以至修正Cookie中的內容。而Session存儲在服務器上,對客戶端是透明的,不存在敏感信息泄露的風險。
假如選用Cookie,比較好的方法是,敏感的信息如賬號密碼等盡量不要寫到Cookie中。最好是像Google、Baidu那樣將Cookie信息加密,提交到服務器後再進行解密,保證Cookie中的信息只要本人能讀得懂。而假如選擇Session就省事多了,反正是放在服務器上,Session裏任何隱私都能夠有效的保護。

3.有效期上的不同

使用過Google的人都曉得,假如登錄過Google,則Google的登錄信息長期有效。用戶不用每次訪問都重新登錄,Google會持久地記載該用戶的登錄信息。要到達這種效果,運用Cookie會是比較好的選擇。只需要設置Cookie的過期時間屬性為一個很大很大的數字。

由於Session依賴於名為JSESSIONID的Cookie,而Cookie JSESSIONID的過期時間默許為–1,只需關閉了閱讀器該Session就會失效,因而Session不能完成信息永世有效的效果。運用URL地址重寫也不能完成。而且假如設置Session的超時時間過長,服務器累計的Session就會越多,越容易招致內存溢出。

4.服務器壓力的不同

Session是保管在服務器端的,每個用戶都會產生一個Session。假如並發訪問的用戶十分多,會產生十分多的Session,耗費大量的內存。因而像Google、Baidu、Sina這樣並發訪問量極高的網站,是不太可能運用Session來追蹤客戶會話的。

而Cookie保管在客戶端,不占用服務器資源。假如並發閱讀的用戶十分多,Cookie是很好的選擇。關於Google、Baidu、Sina來說,Cookie或許是唯一的選擇。

5 .瀏覽器支持的不同

Cookie是需要客戶端瀏覽器支持的。假如客戶端禁用了Cookie,或者不支持Cookie,則會話跟蹤會失效。關於WAP上的應用,常規的Cookie就派不上用場了。

假如客戶端瀏覽器不支持Cookie,需要運用Session以及URL地址重寫。需要註意的是一切的用到Session程序的URL都要進行URL地址重寫,否則Session會話跟蹤還會失效。關於WAP應用來說,Session+URL地址重寫或許是它唯一的選擇。

假如客戶端支持Cookie,則Cookie既能夠設為本瀏覽器窗口以及子窗口內有效(把過期時間設為–1),也能夠設為一切閱讀器窗口內有效(把過期時間設為某個大於0的整數)。但Session只能在本閱讀器窗口以及其子窗口內有效。假如兩個瀏覽器窗口互不相幹,它們將運用兩個不同的Session。(IE8下不同窗口Session相幹)

6.跨域支持上的不同

Cookie支持跨域名訪問,例如將domain屬性設置為“.biaodianfu.com”,則以“.biaodianfu.com”為後綴的一切域名均能夠訪問該Cookie。跨域名Cookie如今被普遍用在網絡中,例如Google、Baidu、Sina等。而Session則不會支持跨域名訪問。Session僅在他所在的域名內有效。
僅運用Cookie或者僅運用Session可能完成不了理想的效果。這時應該嘗試一下同時運用Cookie與Session。Cookie與Session的搭配運用在實踐項目中會完成很多意想不到的效果。

php中Cookie與Session的使用:

php中設置cookie數組的時候,不可以用像php中的那個添加數據的方法:


<?php
setcookie(‘my_cookie[]‘, 1);
setcookie(‘my_cookie[]‘, 2);
print_r($_COOKIE);    // Array ( [my_cookie] => Array ( [0] => 1 )) 
                      // 數組的值添加是添加成功了,不過索引沒有變,後面的數據將前的數據覆蓋了!
由此得到
       my_cookie[],默認指向數據的第一元素的位置,即索引為
0 的位置. 註意與php中的不一樣! 以後用cookie數據記住要指定數組元素索引哦!

$my_cookie[] = 1;
$my_cookie[] = 2;
print_r($my_cookie); //Array ( [0] => 1 [1] => 2) 
?>

刪除 cookie 變量的兩個方法:
1.php

<?php
setcookie(‘user_name_1‘, ‘zhaofei299‘, time()+3600); // 生存期為 1 個小時
setcookie(‘user_name_2‘, ‘ZHAOFEI299‘, time()+3600); // 生存期為 1 個小時
?>

  

2.php

<?php
setcookie(‘user_name_1‘);                // 第一種                
setcookie(‘user_name_2‘, "", time()-1); // 第二種
print_r($_COOKIE);                       // 刷新頁面2下以上會輸出 Array ( [user_name_1] => )

/*為什麽超級全局變量 $_COOKIE 中的 user_name_1 沒有被刪除(變量為空並不代表不存在),而
user_name_2被刪除了? 那是因為兩個刪除變量的方式不同!
第一種: 是設置了 cookie 的生存期, 只不過是將它的值默認設置為空,生存期為與瀏覽器一樣,瀏覽器
關閉時,cookie才會刪除!所以當重新打開一個瀏覽器,輸出地址時,才會發現 cookie 變量全部被刪除了!
將2.php 中兩個 setcookie() 函數部分註釋掉看看(重新輸出了地址)!
第二種: 也是設置了 cookie 的生存期,是使 cookie 的生存期一定過期, cookie 也就被刪除,所以刷
新頁面,客戶端向服務器端發送 cookie 時, $_COOKIE 並沒有能夠得到該cookie變量的值!
*/
?>

  


會話id默認儲放在客戶端Cookie中!

<?php
session_start(); 
print_r($_COOKIE); 
?>

cookie的設置有兩種方法

header(‘set-cookie:user=zhaofei299‘);
setcookie(‘user‘, ‘zhaofei299‘);

會話變量不能被GET數據或POST數據重載!
使用session變量傳遞數組,對象時無需序列化!
使用session變量傳遞對象時,在調用session_start()之前,必須包含該對類對象的定義,反序列化
(serialize)也是如此!
刪除單個會話變量可以使用unset($_SESSION[‘***‘]) 直接刪除!
刪除所有的會話變量不可以用unset($_SESSION),因為這樣會將所有的會話信息刪除,包含存儲在COOKIE
中的PHPSESSID,也就是破壞了兩個頁面之間的會話聯系,應該使用$_SESSION = array();
消除會話id,使頁面之間失去聯系!
session_destroy();
程序清單1.1

<?php
session_start();
header(‘content-type:text/html;charset=utf-8‘);
$_SESSION[‘a‘] = ‘a‘;
$_SESSION[‘b‘] = ‘b‘;
unset($_SESSION);        //測試後,再註釋下看看
$_SESSION[‘user‘] = ‘zhaofei299‘;
echo ‘SESSION_ID: ‘.session_id().‘<br />‘;
echo ‘<a href="3.php" target="_blank">測試下</a>‘;
?>
<?php
session_start();
echo $_SESSION[‘user‘];
echo session_id();         //會話變量改變了
?>

  

會話id(session_id)的兩種方式傳遞:
1.cookie
2.url
因為默認session是基於cookie的,而cookie又是跟隨http協議發送的,所以與cookie一樣,在
session_start()之前不能有任何輸出!
現在主要說一說第二種,通過 url 傳遞會話id
php中已經定義SID這個常量來得到 會話的id
sesssin_id 的使用:

<?php
session_start();
echo defined(‘SID‘)?‘true‘:‘false‘; // true
echo SID; //什麽也沒有? 
?>

  

為什麽SID的值會是null 呢?是它哪裏有問題了?
原因是因為 session 默認是基於 cookie 的,而 SID 只有 session_id 通過 url
傳遞數據時才會被賦值!
在瀏覽器中將 cookie 禁用,你就會發現 SID 有了輸出,而不是 null!
刪除session
要三步實現.

<?php
session_destroy();                         // 第一步: 刪除服務器端session文件,這使用 
setcookie(session_name(),‘‘,time()-3600); // 第二步: 刪除實際的session: 
$_SESSION = array();                       // 第三步: 刪除$_SESSION全局變量數組
?>

  

大家都知道session變量是保存在服務器端的,也就是說session的變量會保存在服務器中一個目錄中,我
們可以在php.ini中的session.save_path 那裏可以找到session文件中保存的地址.

默認的session的生存期是瀏覽的關閉就結束,但要知道會話過期結束後,當打開頁面session_start()會
判斷會話id 是否存在,如果不存在就創建一個,否則將該會話id 的變量載入頁面!因為過期session_id會
被創建一個新的,但它保存在服務器端的session文件並沒有被刪除(關閉瀏覽器,打開session文件保存
地看看),所以要用session_destory()函數清除會話id,並同時清除相應的會話文件,這樣的話才能做到最
徹底的清除!

session_id 使用 url 傳遞session 變量數據時,因為session_start()開啟會話時會判斷會話id 是否存
在,如果不存在就創建一個,否則將該會話id 的變量載入頁面!

而現在是使用url 來傳遞session_id,然而每一次 刷新/進入頁面 都會生成一個會話id,所以頁面之間就
不能得到在另一頁面設置過的session_id 的變量,那麽使用 session也就沒什麽意義了!

解決方法:在session_start()之前,手動設置頁面的session_id,這樣頁面的就可以得到前一頁中所設置的
session變量的,也就實現了會話的傳遞,如下代碼可以說明!

//已禁用 cookie
1.php

<?php
session_start();
$_SESSION[‘user‘] = ‘zhaofei299‘;
echo ‘<a href="2.php?‘.SID.‘">下一頁</a>‘; 
?>

1.php的第4行代碼也可以寫成:echo ‘<a href="2.php">下一頁</a>‘;
可以設置php.ini 中的 session.use_trans_sid 為1,這樣當使用 url 傳遞會話 id 時,
瀏覽器會自動將 session_id 追加到 url 的後面!
就好像 在瀏覽器中 輸入: www.baidu.com 一樣,瀏覽器會自動將其更換成 http://www.baidu.com/

2.php

<?php
session_id($_GET[‘PHPSESSID‘]);   // 手動設置session_id,這種就可以使用前一個頁面的
session_id 的變量了,也就實現了會話!
session_start(); 
print_r($_SESSION);
?>

  

常用session函數:

bool   session_start(void); 初始化session
bool   session_destroy(void): 刪除服務器端session關聯文件。
string session_id() 當前session的id
string session_name() 當前存取的session名稱,也就是客戶端保存session ID的cookie名稱.默認
PHPSESSID。
array session_get_cookie_params() 與這個session相關聯的session的細節.
string session_cache_limiter() 控制使用session的頁面的客戶端緩存
ini    session_cache_expire() 控制客戶端緩存時間
bool   session_destroy()     刪除服務器端保存session信息的文件
void   session_set_cookie_params ( int lifetime [, string path [, string domain [, bool
secure [, bool httponly]]]] )設置與這個session相關聯的session的細節
bool session_set_save_handler ( callback open, callback close, callback read, callback
write, callback destroy, callback gc )定義處理session的函數,(不是使用默認的方式)
bool session_regenerate_id([bool delete_old_session]) 分配新的session id  

  

PHP中Cookie與Session的異同以及使用