新聞中心
. PHP 的Cookie

cookie 是一種在遠程瀏覽器端儲存數(shù)據(jù)并以此來跟蹤和識別用戶的機制。
PHP 在http 協(xié)議的頭信息里發(fā)送cookie,因此 setcookie() 函數(shù)必須在其它信息被輸出到瀏覽器
前調(diào)用,這和對 header() 函數(shù)的限制類似。
1.1 設(shè)置cookie:
可以用 setcookie()或 setrawcookie()函數(shù)來設(shè)置 cookie。也可以通過向客戶端直接發(fā)送http 頭來設(shè)置。
1.1.1 使用 setcookie()函數(shù)設(shè)置cookie:
bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure [, bool
httponly]]]]]] )
name: cookie 變量名
value:cookie 變量的值
expire: 有效期結(jié)束的時間
path: 有效目錄
domain: 有效域名,頂級域唯一
secure: 如果值為 1,則cookie 只能在https 連接上有效,如果為默認值 0,則http 和 https 都可以。
例子:
代碼片段
- $value = 'something from somewhere';
- setcookie("TestCookie", $value); /* 簡單 cookie設(shè)置 */
- setcookie("TestCookie", $value, time()+3600); /* 有效期 1個小時 */
- setcookie("TestCookie", $value, time()+3600, "/~rasmus/",
- ".example.com", 1); /* 有效目錄 /~rasmus,有效域名 example.com及其所有子域名
- */
- ?>
設(shè)置多個 cookie 變量:setcookie('var[a]','value'); 用數(shù)組來表示變量,但他的下標不用引號。這
樣就可以用$_COOKIE[‘var’][‘a(chǎn)’]來讀取該COOKIE 變量。
1.1.2. 使用 header()設(shè)置cookie;
header("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[;...]]");
后面的參數(shù)和上面列出 setcookie 函數(shù)的參數(shù)一樣。
比如:
代碼片段
- $value = 'something from somewhere';
- header("Set-Cookie:name=$value");
1.2 Cookie 的讀取:
直接用php 內(nèi)置超級全局變量$_COOKIE 就可以讀取瀏覽器端的cookie。
面例子中設(shè)置了cookie "TestCookie",現(xiàn)在我們來讀?。?/p>
代碼片段
- print $_COOKIE['TestCookie'];
COOKIE 是不是被輸出了?!
1.3 刪除cookie
只需把有效時間設(shè)為小于當前時間,和把值設(shè)置為空。例如:
代碼片段
- setcookie("name", "", time()-1);
用header()類似。
1.4 常見問題解決:
1) 用 setcookie()時有錯誤提示,可能是因為調(diào)用setcookie()前面有輸出或空格。也可能你的文
檔是從其他字符集轉(zhuǎn)換過來,文檔后面可能帶有 BOM 簽名(就是在文件內(nèi)容添加一些隱藏
的BOM 字符)。解決的辦法就是使你的文檔不出現(xiàn)這種情況。還有通過使用ob_start()函數(shù)
也能處理一點。
2) $_COOKIE 受magic_quotes_gpc 影響,可能自動轉(zhuǎn)義。
3) 使用的時候,有必要測試用戶是否支持cookie。
1.5 cookie 工作機理:
有些學習者比較沖動,沒心思把原理研究,所以我把它放后面。
a) 服務(wù)器通過隨著響應(yīng)發(fā)送一個http 的Set-Cookie 頭,在客戶機中設(shè)置一個cookie(多個cookie要多個頭)。
b) 客戶端自動向服務(wù)器端發(fā)送一個http 的cookie 頭,服務(wù)器接收讀取。
HTTP/1.x 200 OK
X-Powered-By: PHP/5.2.1
Set-Cookie: TestCookie=something from somewhere; path=/
Expires: Thu, 19 Nov 2007 18:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-type: text/html
這一行實現(xiàn)了cookie 功能,收到這行后
Set-Cookie: TestCookie=something from somewhere; path=/
瀏覽器將在客戶端的磁盤上創(chuàng)建一個cookie 文件,并在里面寫入:
TestCookie=something from somewhere;
/
這一行就是我們用 setcookie('TestCookie','something from somewhere','/'); 的結(jié)果。也就是用
header('Set-Cookie: TestCookie=something from somewhere; path=/');的結(jié)果。
2. PHP 的SESSION
session 使用過期時間設(shè)為0 的cookie,并且將一個稱為session ID 的唯一標識符(一長串字符串),
在服務(wù)器端同步生成一些 session 文件(可以自己定義 session 的保存類型),與用戶機關(guān)聯(lián)起來。web
應(yīng)用程序存貯與這些 session 相關(guān)的數(shù)據(jù),并且讓數(shù)據(jù)隨著用戶在頁面之間傳遞。
訪問網(wǎng)站的來客會被分配一個唯一的標識符,即所謂的 SESSION ID。它要么存放在客戶端的
cookie,要么經(jīng)由 URL 傳遞。
SESSION 允許用戶注冊任意數(shù)目的變量并保留給各個請求使用。當來客訪問網(wǎng)站時,PHP 會自
動(如果 session.auto_start 被設(shè)為 1 )或在用戶請求時(由 session_start() 明確調(diào)用或
session_register() 暗中調(diào)用)檢查請求中是否發(fā)送了特定的SESSION ID。如果是,則之前保存的環(huán)
境就被重建。
2.1 SESSION ID 的傳送
2.1.1 通過 cookie 傳送 SESSION ID
使用 session_strt()調(diào)用 session,服務(wù)器端在生成session 文件的同時,生成 session ID 哈希值和
默認值為PHPSESSID 的session name,并向客戶端發(fā)送變量為(默認的是)PHPSESSID(session name),
值為一個 128 位的哈希值。服務(wù)器端將通過該 cookie 與客戶端進行交互。
session 變量的值經(jīng)php 內(nèi)部序列化后保存在服務(wù)器機器上的文本文件中,和客戶端的變量名默
認情況下為PHPSESSID 的coolie 進行對應(yīng)交互。
即服務(wù)器自動發(fā)送了 http 頭:header('Set-Cookie: session_name()=session_id(); path=/'); 即
setcookie(session_name(),session_id());
當從該頁跳轉(zhuǎn)到的新頁面并調(diào)用session_start()后,PHP 將檢查與給定ID 相關(guān)聯(lián)的服務(wù)器端存貯
的session 數(shù)據(jù),如果沒找到,則新建一個數(shù)據(jù)集。
2.1.2 通過 URL 傳送 session ID
只有在用戶禁止使用cookie 的時候才用這種方法,因為瀏覽器cookie 已經(jīng)通用,為安全起見,
可不用該方法。
xxx,也可以通過
POST 來傳遞 session 值。
2.2 session 基本用法實例
代碼片段
默認php5.2.1下,SID只有在 cookie被寫入的同時才會有值,如果該 session
對應(yīng)的 cookie 已經(jīng)存在,那么 SID將為 (未定義)空
- */
- ?>
- 代碼片段
- // page2.php
- session_start();
- print $_SESSION['animal']; // 打印出單個 session
- var_dump($_SESSION); // 打印出page1.php傳過來的 session值
- ?>
2.3 使用session 函數(shù)控制頁面緩存
很多情況下,我們要確定我們的網(wǎng)頁是否在客戶端緩存,或要設(shè)置緩存的有效時間,比如我們
的網(wǎng)頁上有些敏感內(nèi)容并且要登錄才能查看,如果緩存到本地了,可以直接打開本地的緩存就可以
不登錄而瀏覽到網(wǎng)頁了。
使用 session_cache_limiter('private');可以控制頁面客戶端緩存,必須在 session_start()之前調(diào)用。
更多參數(shù)見http://blog.chinaunix.net/u/27731/showart.php?id=258087 的客戶端緩存控制。
控制客戶端緩存時間用 session_cache_expire(int); 單位(s)。也要在session_start()前調(diào)用。
這只是使用 session 的情況下控制緩存的方法,我們還可以在header()中控制控制頁面的緩存。
2.4 刪除session
要三步實現(xiàn)。
代碼片段
- session_destroy(); // 第一步: 刪除服務(wù)器端 session文件,這使用
- setcookie(session_name(),'',time()-3600); // 第 二 步 : 刪 除 實 際 的
- session:
- $_SESSION = array(); // 第三步: 刪除$_SESSION全局變量數(shù)組
- ?>
2.5 session 在PHP 大型web 應(yīng)用中的使用
對于訪問量大的站點,用默認的 session 存貯方式并不適合,目前最優(yōu)的方法是用數(shù)據(jù)庫存取
session。這時,函數(shù)bool session_set_save_handler ( callback open, callback close, callback read, callback
write, callback destroy, callback gc )就是提供給我們解決這個問題的方案。
該函數(shù)使用的6 個函數(shù)如下:
1. bool open() 用來打開會話存儲機制。
2. bool close(-)關(guān)閉會話存儲操作。
3. mixde read() 從存儲中裝載session 數(shù)據(jù)時使用這個函數(shù)。
4. bool write() 將給定 session ID 的所有數(shù)據(jù)寫到存儲中。
5. bool destroy() 破壞與指定的 session ID 相關(guān)聯(lián)的數(shù)據(jù)。
6. bool gc() 對存儲系統(tǒng)中的數(shù)據(jù)進行垃圾收集。
例子見php 手冊 session_set_save_handler() 函數(shù)。
如果用類來處理,用
代碼片段
- session_set_save_handler(
- array('className','open'),
- array('className','close'),
- array('className','read'),
- array('className','write'),
- array('className','destroy'),
- array('className','gc'),
- )
調(diào)用className 類中的 6 個靜態(tài)方法。className 可以實例化對象就不用調(diào)用靜態(tài)方法,但是用
靜態(tài)成員不用生成對象,性能更好。
2.6 常用session 函數(shù):
bool session_start(void) 初始化 session。
bool session_destroy(void) 刪除服務(wù)器端 session 關(guān)聯(lián)文件。
string session_id() 當前session 的id。
string session_name() 當前存取的session 名稱,也就是客戶端保存session ID 的cookie 名稱.默
認PHPSESSID。
array session_get_cookie_params() 與這個session 相關(guān)聯(lián)的 session 的細節(jié)。
string session_cache_limiter() 控制使用 session 的頁面的客戶端緩存。
ini session_cache_expire() 控制客戶端緩存時間。
bool session_destroy() 刪除服務(wù)器端保存 session 信息的文件。
void session_set_cookie_params ( int lifetime [, string path [, string domain [, bool secure [, bool
httponly]]]] ) 設(shè)置與這個session 相關(guān)聯(lián)的 session 的細節(jié)。
bool session_set_save_handler ( callback open, callback close, callback read, callback write, callback
destroy, callback gc ) 定義處理session 的函數(shù)(不是使用默認的方式)。
bool session_regenerate_id([bool delete_old_session]) 分配新的session id
2.7 session 安全問題
攻擊者通過投入很大的精力嘗試獲得現(xiàn)有用戶的有效 session ID,有了session id,他們就有可能
能夠在系統(tǒng)中擁有與此用戶相同的能力。
因此,我們主要解決的思路是效驗session ID 的有效性。
代碼片段
- if(!isset($_SESSION['user_agent'])){
- $_SESSION['user_agent'] = $_SERVER['REMOTE_ADDR'] .
- $_SERVER['HTTP_USER_AGENT'];
- }
- /* 如果用戶 session ID是偽造 */
- elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] .
- $_SERVER['HTTP_USER_AGENT']) {
- session_regenerate_id();
- }
- ?>
2.8 Session 通過cookie 傳遞和通過SID 傳遞的不同
在 php5.2.1 的session 的默認配置的情況下,當生成session 的同時,服務(wù)器端將在發(fā)送header
set-cookie 同時生成預(yù)定義超級全局變量 SID(也就是說,寫入 cookie 和拋出 SID 是等價的),當
$_COOKIE['PHPSESSID']存在以后,將不再寫入 cookie,也不再生成超級全局變量SID,此時,SID
將是空的。
2.9 session 使用實例
代碼片段
- /**
- * 效驗 session的合法性
- *
- */
- function sessionVerify() {
- if(!isset($_SESSION['user_agent'])){
- $_SESSION['user_agent'] = MD5($_SERVER['REMOTE_ADDR']
- .$_SERVER['HTTP_USER_AGENT']);
- }
- /* 如果用戶 session ID是偽造,則重新分配 session ID */
- elseif ($_SESSION['user_agent']!=MD5($_SERVER['REMOTE_ADDR']
- . $_SERVER['HTTP_USER_AGENT'])) {
- session_regenerate_id();
- }
- }
- /**
- * 銷毀 session
- * 三步完美實現(xiàn),不可漏
- *
- */
- function sessionDestroy() {
- session_destroy();
- setcookie(session_name(),'',time()-3600);
- $_SESSION = array();
- }
- ?>
注明:
session 出現(xiàn)頭信息已經(jīng)發(fā)出的原因與cookie 一樣。
在php5 中,所有php session 的注冊表配置選項都是編程時可配置的,一般情況下,我們是不用
修改其配置的。要了解php 的session 注冊表配置選項,請參考手冊的 Session 會話處理函數(shù)處。
文章標題:PHP中cookie和session的分析
文章網(wǎng)址:http://m.fisionsoft.com.cn/article/coccged.html


咨詢
建站咨詢
