與客戶端進行交互
1. PHP 的COOKIE
cookie 是一種在遠程瀏覽器端儲存數據并以此來跟蹤和識別用戶的機制。
PHP 在http 協議的頭信息里發送cookie,因此 setcookie() 函數必須在其它信息被輸出到瀏覽器
前調用,這和對 header() 函數的限制類似。
1.1 設置cookie:
可以用 setcookie()或 setrawcookie()函數來設置 cookie。也可以通過向客戶端直接發送http 頭來
設置。
1.1.1 使用 setcookie()函數設置cookie:
bool setcookie ( string name [, string html' target='_blank'>value [, int expire [, string path [, string domain [, bool secure [, bool
httponly]]]]]] )
name: cookie 變量名
value: cookie 變量的值
expire: 有效期結束的時間
path: 有效目錄
domain: 有效域名,頂級域唯一
secure: 如果值為 1,則cookie 只能在https 連接上有效,如果為默認值 0,則http 和 https 都可
以。
例子:
代碼片段
<?php $value = 'something from somewhere'; setcookie("TestCookie", $value); /* 簡單 cookie設置 */ setcookie("TestCookie", $value, time()+3600); /* 有效期 1個小時 */ setcookie("TestCookie", $value, time()+3600, "/~rasmus/", ".example.com", 1); /* 有效目錄 /~rasmus,有效域名 example.com及其所有子域名 */ ?>
設置多個 cookie 變量:setcookie('var[a]','value'); 用數組來表示變量,但他的下標不用引號。這
樣就可以用$_COOKIE[‘var’][‘a’]來讀取該COOKIE 變量。
1.1.2. 使用 header()設置cookie;
header("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[;...]]");
后面的參數和上面列出 setcookie 函數的參數一樣。
比如:
代碼片段
$value = 'something from somewhere';
header("Set-Cookie:name=$value");
1.2 Cookie 的讀取:
直接用php 內置超級全局變量$_COOKIE 就可以讀取瀏覽器端的cookie。
上面例子中設置了cookie "TestCookie",現在我們來讀?。?/p>
代碼片段
print $_COOKIE['TestCookie'];
COOKIE 是不是被輸出了?!
1.3 刪除cookie
只需把有效時間設為小于當前時間,和把值設置為空。例如:
代碼片段
setcookie("name", "", time()-1);
用header()類似。
1.4 常見問題解決:
1) 用 setcookie()時有錯誤提示,可能是因為調用setcookie()前面有輸出或空格。也可能你的文
檔是從其他字符集轉換過來,文檔后面可能帶有 BOM 簽名(就是在文件內容添加一些隱藏
的BOM 字符)。解決的辦法就是使你的文檔不出現這種情況。還有通過使用ob_start()函數
也能處理一點。
2) $_COOKIE 受magic_quotes_gpc 影響,可能自動轉義。
3) 使用的時候,有必要測試用戶是否支持cookie。
1.5 cookie 工作機理:
有些學習者比較沖動,沒心思把原理研究,所以我把它放后面。
a) 服務器通過隨著響應發送一個http 的Set-Cookie 頭,在客戶機中設置一個cookie(多個cookie
要多個頭)。
b) 客戶端自動向服務器端發送一個http 的cookie 頭,服務器接收讀取。
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
這一行實現了cookie 功能,收到這行后
Set-Cookie: TestCookie=something from somewhere; path=/
瀏覽器將在客戶端的磁盤上創建一個cookie 文件,并在里面寫入:
TestCookie=something from somewhere;
/
這一行就是我們用 setcookie('TestCookie','something from somewhere','/'); 的結果。也就是用
header('Set-Cookie: TestCookie=something from somewhere; path=/');的結果。
2. PHP 的SESSION
session 使用過期時間設為0 的cookie,并且將一個稱為session ID 的唯一標識符(一長串字符串),
在服務器端同步生成一些 session 文件(可以自己定義 session 的保存類型),與用戶機關聯起來。web
應用程序存貯與這些 session 相關的數據,并且讓數據隨著用戶在頁面之間傳遞。
訪問網站的來客會被分配一個唯一的標識符,即所謂的 SESSION ID。它要么存放在客戶端的
cookie,要么經由 URL 傳遞。
SESSION 允許用戶注冊任意數目的變量并保留給各個請求使用。當來客訪問網站時,PHP 會自
動(如果 session.auto_start 被設為 1 )或在用戶請求時(由 session_start() 明確調用或
session_register() 暗中調用)檢查請求中是否發送了特定的SESSION ID。如果是,則之前保存的環
境就被重建。
2.1 SESSION ID 的傳送
2.1.1 通過 cookie 傳送 SESSION ID
使用 session_start()調用 session,服務器端在生成session 文件的同時,生成 session ID 哈希值和
默認值為PHPSESSID 的session name,并向客戶端發送變量為(默認的是)PHPSESSID(session name),
值為一個 128 位的哈希值。服務器端將通過該 cookie 與客戶端進行交互。
session 變量的值經php 內部序列化后保存在服務器機器上的文本文件中,和客戶端的變量名默
認情況下為PHPSESSID 的coolie 進行對應交互。
即服務器自動發送了 http 頭:header('Set-Cookie: session_name()=session_id(); path=/'); 即
setcookie(session_name(),session_id());
當從該頁跳轉到的新頁面并調用session_start()后,PHP 將檢查與給定ID 相關聯的服務器端存貯
的session 數據,如果沒找到,則新建一個數據集。
2.1.2 通過 URL 傳送 session ID
只有在用戶禁止使用cookie 的時候才用這種方法,因為瀏覽器cookie 已經通用,為安全起見,
可不用該方法。
<a href="p.php?<?php print session_name() ?>=<?php print session_id() ?>">xxx</a>,也可以通過
POST 來傳遞 session 值。
2.2 session 基本用法實例
代碼片段
<?php
// page1.php
session_start();
echo 'Welcome to page #1';
/* 創建 session變量并給 session變量賦值 */
$_SESSION['favcolor'] = 'green';
$_SESSION['animal'] = 'cat';
$_SESSION['time'] = time();
// 如果客戶端使用 cookie,可直接傳遞 session到page2.php
echo '<br /><a href="page2.php">page 2</a>';
// 如果客戶端禁用 cookie
echo '<br /><a href="page2.php?' . SID . '">page 2</a>';
/*
默認php5.2.1下,SID只有在 cookie被寫入的同時才會有值,如果該 session
對應的 cookie 已經存在,那么 SID將為 (未定義)空
*/
?>
代碼片段
<?php
// page2.php
session_start();
print $_SESSION['animal']; // 打印出單個 session
var_dump($_SESSION); // 打印出page1.php傳過來的 session值
?>
2.3 使用session 函數控制頁面緩存
很多情況下,我們要確定我們的網頁是否在客戶端緩存,或要設置緩存的有效時間,比如我們
的網頁上有些敏感內容并且要登錄才能查看,如果緩存到本地了,可以直接打開本地的緩存就可以
不登錄而瀏覽到網頁了。
使用 session_cache_limiter('private');可以控制頁面客戶端緩存,必須在 session_start()之前調用。
控制客戶端緩存時間用 session_cache_expire(int); 單位(s)。也要在session_start()前調用。
這只是使用 session 的情況下控制緩存的方法,我們還可以在header()中控制控制頁面的緩存。
2.4 刪除session
要三步實現。
代碼片段
<?php
session_destroy(); // 第一步: 刪除服務器端 session文件,這使用
setcookie(session_name(),'',time()-3600); // 第 二 步 : 刪 除 實 際 的
session:
$_SESSION = array(); // 第三步: 刪除$_SESSION全局變量數組
?>
2.5 session 在PHP 大型web 應用中的使用
對于訪問量大的站點,用默認的 session 存貯方式并不適合,目前最優的方法是用數據庫存取
session。這時,函數bool session_set_save_handler ( callback open, callback close, callback read, callback
write, callback destroy, callback gc )就是提供給我們解決這個問題的方案。
該函數使用的6 個函數如下:
1. bool open() 用來打開會話存儲機制。
2. bool close() 關閉會話存儲操作。
3. mixde read() 從存儲中裝載session 數據時使用這個函數。
4. bool write() 將給定 session ID 的所有數據寫到存儲中。
5. bool destroy() 破壞與指定的 session ID 相關聯的數據。
6. bool gc() 對存儲系統中的數據進行垃圾收集。
例子見php 手冊 session_set_save_handler() 函數。
如果用類來處理,用
代碼片段
session_set_save_handler(
array('className','open'),
array('className','close'),
array('className','read'),
array('className','write'),
array('className','destroy'),
array('className','gc'),
)
調用className 類中的 6 個靜態方法。className 可以實例化對象就不用調用靜態方法,但是用
靜態成員不用生成對象,性能更好。
2.6 常用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
2.7 session 安全問題
攻擊者通過投入很大的精力嘗試獲得現有用戶的有效 session ID,有了session id,他們就有可能
能夠在系統中擁有與此用戶相同的能力。
因此,我們主要解決的思路是效驗session ID 的有效性。
代碼片段
<?php
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 的同時,服務器端將在發送header
set-cookie 同時生成預定義超級全局變量 SID(也就是說,寫入 cookie 和拋出 SID 是等價的),當
$_COOKIE['PHPSESSID']存在以后,將不再寫入 cookie,也不再生成超級全局變量SID,此時,SID
將是空的。
2.9 session 使用實例
代碼片段
<?php
/**
* 效驗 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
* 三步完美實現,不可漏
*
*/
function sessionDestroy() {
session_destroy();
setcookie(session_name(),'',time()-3600);
$_SESSION = array();
}
?>
注明:
session 出現頭信息已經發出的原因與cookie 一樣。
在php5 中,所有php session 的注冊表配置選項都是編程時可配置的,一般情況下,我們是不用
修改其配置的。要了解php 的session 注冊表配置選項,請參考手冊的 Session 會話處理函數處。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答