1.cookie簡介

  • Cookie存儲在客戶端瀏覽器中的數據
    我們通過Cookie來跟蹤與存儲用戶數據

  • 一般情況下,Cookie通過HTTP headers從服務端返回到客戶端

  • 多數web程序都支持Cookie的操作
    因為Cookie是存在於HTTP的標頭之中
    所以必須在其他資訊輸出以前進行設置,類似於header函數使用限制

  • PHP通過setcookie函數進行Cookie的設置
    任何從瀏覽器發回的Cookie
    PHP都會自動的將它存儲$_COOKIE全局變量之中,
    因此我們可以通過$_COOKIE['key']的形式來讀取某個 Cookie值

  • PHP中的Cookie具有非常廣泛的使用,經常用來存儲用戶的登錄資訊購物車等,
    且在使用會話Session時通常使用Cookie存儲會話id識別用戶

  • Cookie具備有效期
    有效期結束之後Cookie自動的從客戶端刪除

  • 同時為了進行安全控制Cookie還可以設置域跟路徑,稍後章節會詳細筆記。

了解Cookie的概念以及用途,觀察代碼中輸出的Cookie值,
然後刷新頁面,再次觀察預覽框中輸出的Cookie值:

<?php
setcookie('test', time());
ob_start();
print_r($_COOKIE); 
$content = ob_get_contents();
$content = str_replace(" ", '&nbsp;', $content);
ob_clean();
header("content-type:text/html; charset=utf-8");
echo '當前的Cookie為:<br>';
echo nl2br($content);

這里本地運行採用的是PHPStudy集成環境
安裝好集成環境之後創建虛擬主機 / 站點
即下面的操作是基於之前的這篇筆記(<+++點擊前往+++>)的後續;
之後再往其中添加代碼文件:

保存好文件後開啟環境:

最後再瀏覽器輸入虛擬站點網址即可觀察代碼的運行結果:

由於

  • Cookie具備有效期
    有效期結束之後Cookie自動的從客戶端刪除

    我們此時刷新一下頁面,可以看到窗口會輸出不同的結果:


2. 設置cookie

  • PHP設置Cookie最常用的方法就是使用setcookie函數,
    setcookie具有7可選參數
    我們常用到的為前 5 個:
  • name( Cookie名)可以通過$_COOKIE['name']進行訪問;
  • value(Cookie的值)
  • expire(過期時間) Unix時間戳格式,默認為0,表示瀏覽器關閉即失效
  • path(有效路徑)如果路徑設置為'/',則整個網站都有效
  • domain(有效域)默認整個域名都有效,如果設置了'www.imooc.com',則只在www子域中有效
$value = 'test';
setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600);  //有效期一小時
setcookie("TestCookie", $value, time()+3600, "/path/", "imooc.com"); //設置路徑與域
  • PHP中還有一個設置Cookie的函數setrawcookie
    setrawcookiesetcookie基本一樣,
    唯一的不同就是value值 不會自動的進行urlencode
    因此在需要的時候要手動的進行urlencode
setrawcookie('cookie_name', rawurlencode($value), time()+60*60*24*365); 
  • 因為Cookie是通過HTTP標頭進行設置的
    所以也可以直接使用header方法進行設置。
header("Set-Cookie:cookie_name=value");

區別:
setcookie() 把實值傳到對應的參數位置即可;
header() 主要是要以鍵值對的方式傳值;

demo:

<?php
$value = time();
//在這里設置一個名為test的Cookie
setcookie('test', $value);
if (isset($_COOKIE['test'])) {
    echo 'success';
}


3. cookie的刪除與過期時間

  • php中沒有刪除Cookie函數,在PHP中刪除cookie也是採用setcookie函數來實現。
setcookie('test', '', time()-1); 
  • cookie過期時間設置到當前時間之前
    則該cookie會自動失效
    也就達到了刪除cookie的目的。

  • 之所以這么設計是因為cookie是通過HTTP的標頭傳遞的
    客戶端根據服務端返回的Set-Cookie段來進行cookie的設置
    如果刪除cookie需要使用新的Del-Cookie來實現,
    HTTP頭就會變得復雜

  • 實際上僅通過Set-Cookie就可以簡單明了的實現Cookie設置、更新與刪除

  • 也可以直接通過header來刪除cookie。

header("Set-Cookie:test=1393832059; expires=".gmdate('D, d M Y H:i:s \G\M\T', time()-1));

這里用到了gmdate,用來生成格林威治標準時間,以便排除時差的影響

demo(刪除test的cookie值):

<?php
setcookie('test', time());

//在這里試著刪除test的cookie值
setcookie('test', '', time()-1); 

var_dump($_COOKIE);


4. cookie的有效路徑

  • cookie中的路徑用來控制 設置的cookie哪個路徑下有效
    默認為'/',在所有路徑下都有,

    當設定了其他路徑之後,則只在設定的路徑以及其子路徑下有效,
    例如:

setcookie('test', time(), 0, '/path');

上面的設置會使test/path以及子路徑/path/xxx下都有效,
但是在根目錄下就讀取不到test的cookie值。

  • 一般情況下,大多是使用所有路徑的,
    只有在極少數有特殊需求的時候,會設置路徑,
    這種情況下只在指定的路徑中才會傳遞cookie值
    可以節省數據的傳輸增強安全性以及提高性能

  • 當我們設置有效路徑的時候,
    不在當前路徑的時候則看不到當前cookie

setcookie('test', '1',0, '/path');  
var_dump($_COOKIE['test']); 


5. session與cookie的異同(結合第八節)

  • cookie數據存儲在客戶端
    建立起用戶與服務器之間的聯系
    通常可以解決很多問題,

  • 但是cookie仍然具有一些局限
    1.cookie 相對不是太安全,容易被盜用導致cookie欺騙
    2.單個cookie的值最大隻能存儲4k
    3.```每次請求都要進行網路傳輸,佔用帶寬```


  • session是將用戶的會話數據存儲在服務端
    沒有大小限制
    通過一個session_id進行用戶識別

  • PHP 默認情況下
    是通過cookie來保存 session id的,
    因此從某種程度上來說,seesion依賴於cookie

  • 但這不是絕對的,session id也可以 通過參數來實現

  • 只要是能將session id 傳遞到服務端進行識別機制, 都可以使用session

綜合demo:

<?php
//開始使用session
session_start();

//設置一個session
$_SESSION['test'] = time();

//顯示當前的session_id
echo "session_id:".session_id()."<br>"."<br>";

//讀取session值
echo $_SESSION['test']."<br>";

//銷毀一個session
unset($_SESSION['test']);

echo "<br>";
var_dump($_SESSION);

運行結果:

session_id:q7itj4n5diegt24cg3gh8s4j33

1552570800

array(0) {
}


6. 使用session

在PHP中使用session非常簡單
先執行session_start方法開啟session
然後通過全局變量$_SESSION進行session讀寫

session_start();
$_SESSION['test'] = time();
var_dump($_SESSION);
  • session會自動的對要設置的值進行encodedecode
    因此session可以支持任意數據類型,包括數據對象等。
session_start();
$_SESSION['ary'] = array('name' => 'jobs');
$_SESSION['obj'] = new stdClass();
var_dump($_SESSION);
  • 默認情況下,session是以文件形式存儲在服務器上的,
    因此當一個頁面 開啟了session之後,會獨占這個session文件
    這樣會導致當前用戶其他並發訪問 無法執行等待
    可以採用緩存或者數據庫形式存儲來解決這個問題。

demo:

<?php
//在這里設置name的session值為jobs
session_start();
echo $_SESSION['name'] = 'jobs';

echo '<br>'.'-----------------------'.'<br>';
session_start();
$_SESSION['test'] = time();
var_dump($_SESSION).'<br>';

echo '-----------------------'.'<br>';
$_SESSION['ary'] = array('name' => 'jobs');
$_SESSION['obj'] = new stdClass();
var_dump($_SESSION).'<br>';

運行結果:

jobs
-----------------------
array(2) {
  ["name"]=>
  string(4) "jobs"
  ["test"]=>
  int(1552575628)
}
-----------------------
array(4) {
  ["name"]=>
  string(4) "jobs"
  ["test"]=>
  int(1552575628)
  ["ary"]=>
  array(1) {
    ["name"]=>
    string(4) "jobs"
  }
  ["obj"]=>
  object(stdClass)#1 (0) {
  }
}


7. 刪除與銷毀session

  • 刪除某個session值可以使用PHP的unset函數,
    刪除後就會從全局變量$_SESSION去除,無法訪問。
session_start();
$_SESSION['name'] = 'jobs';
unset($_SESSION['name']);
echo $_SESSION['name']; //提示name不存在
  • 如果要刪除所有的session
    可以使用session_destroy函數銷毀當前session
    session_destroy刪除所有數據
    但是session_id仍然存在。
session_start();
$_SESSION['name'] = 'jobs';
$_SESSION['time'] = time();
session_destroy();

值得注意的是,
session_destroy並不會立即的銷毀全局變量$_SESSION中的值,
只有當下次再訪問的時候,
$_SESSION才為空,
因此如果需要立即銷毀$_SESSION,可以使用unset函數。

session_start();
$_SESSION['name'] = 'jobs';
$_SESSION['time'] = time();
unset($_SESSION);
session_destroy(); 
var_dump($_SESSION); //此時已為空
  • 如果需要同時銷毀cookie中的session_id
    通常在用戶退出的時候可能會用到,
    則還需要顯式地調用setcookie方法刪除session_idcookie值

綜合demo:

<?php
session_start();
$_SESSION['name'] = 'jobs';
var_dump($_SESSION).'<br>';
echo '<br>'.'-----------------------'.'<br>';

//在這里刪除name的session值
unset($_SESSION['name']);
echo $_SESSION['name'];
var_dump($_SESSION).'<br>';
echo '<br>'.'-----------------------'.'<br>';

$_SESSION['name'] = 'jobs';
$_SESSION['time'] = time();
var_dump($_SESSION).'<br>';
echo '<br>'.'-----------------------'.'<br>';

session_destroy();
var_dump($_SESSION).'<br>';
echo '<br>'.'-----------------------'.'<br>';

unset($_SESSION);
session_destroy(); 
var_dump($_SESSION); //此時已為空

運行結果:

array(1) {
  ["name"]=>
  string(4) "jobs"
}

-----------------------
array(0) {
}

-----------------------
array(2) {
  ["name"]=>
  string(4) "jobs"
  ["time"]=>
  int(1552636576)
}

-----------------------
array(2) {
  ["name"]=>
  string(4) "jobs"
  ["time"]=>
  int(1552636576)
}

-----------------------
NULL


8. 使用session來存儲用戶的登錄資訊(結合第五節)

  • session可以用來存儲多種類型的數據
    因此具有很多的用途
    常用來存儲用戶的登錄資訊,購物車數據,或者一些臨時使用的暫存數據等。

  • 用戶在登錄成功以後
    通常可以將用戶的資訊存儲在session中,
    一般會單獨的將一些重要的欄位 單獨存儲
    然後所有的用戶資訊獨立存儲

$_SESSION['uid'] = $userinfo['uid'];//重要欄位單獨存儲
$_SESSION['userinfo'] = $userinfo;//所有的用戶資訊獨立存儲
支持存儲的類型不同
  • 一般來說,登錄資訊既可以存儲在sessioin中,也可以存儲在cookie
    他們之間的差別在於session可以方便的存取多種數據類型
    cookie只支持字元串類型
對於高安全性的數據處理不同
  • 同時對於一些安全性比較高數據
    cookie需要進行格式化加密存儲
    session存儲在服務端則安全性較高
  • session會自動的對要設置的值進行encodedecode
    因此session可以支持任意數據類型,包括數據對象等)。

demo:

<?php
session_start();
//假設用戶登錄成功獲得了以下用戶數據
$userinfo = array(
    'uid'  => 10000,
    'name' => 'spark',
    'email' => 'spark@imooc.com',
    'sex'  => 'man',
    'age'  => '18'
);
header("content-type:text/html; charset=utf-8");

/* 將用戶資訊保存到session中 */
$_SESSION['uid'] = $userinfo['uid'];
$_SESSION['name'] = $userinfo['name'];
$_SESSION['userinfo'] = $userinfo;

//---------------------------------------------------------
//* 將用戶數據保存到cookie中的一個簡單方法 */
$secureKey = 'imooc'; //加密密鑰
$str = serialize($userinfo); //將用戶資訊序列化
echo $str.'<br>';
echo '<br>'.'-----------------------'.'<br>';


//下面這行代碼對用戶資訊進行加密
$str = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($secureKey), $str, MCRYPT_MODE_ECB));
echo $str.'<br>';
echo '<br>'.'-----------------------'.'<br>';

//將加密後的用戶數據存儲到cookie中
setcookie('userinfo', $str);

//當需要使用時進行解密
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($secureKey), base64_decode($str), MCRYPT_MODE_ECB);
echo $str.'<br>';
echo '<br>'.'-----------------------'.'<br>';
$uinfo = unserialize($str);
echo "解密後的用戶資訊:<br>";
print_r($uinfo);

運行結果:

a:5:{s:3:"uid";i:10000;s:4:"name";s:5:"spark";s:5:"email";s:15:"spark@imooc.com";s:3:"sex";s:3:"man";s:3:"age";s:2:"18";}

-----------------------
QO+GE6UHWGGverdp4OvZnTKeHCo0eAxzyQcc6bKWxNmuoowg/gVIFHyppMx+o1z3aQgw0yxPAv5jRQl64eTJ/agwKlE6no4tHbg67O2Zzqj4axDHe6Gm/iUoMicavECJE1uGgDBKvvt6HkVs78BswwFEOj2r/MvuKsYXVUDv+Bk=

-----------------------
a:5:{s:3:"uid";i:10000;s:4:"name";s:5:"spark";s:5:"email";s:15:"spark@imooc.com";s:3:"sex";s:3:"man";s:3:"age";s:2:"18";}

-----------------------
解密後的用戶資訊:
Array
(
    [uid] => 10000
    [name] => spark
    [email] => spark@imooc.com
    [sex] => man
    [age] => 18
)

主要參考資料(慕課網.PHP進階篇)