天天看點

面試-PHP篇-cookie和session

一、Cookie

(1)工作原理

        Cookie 是一種在遠端浏覽器端儲存資料并以此來跟蹤和識别使用者的機制,是一種由伺服器向用戶端發送的片段資訊。

        Cookie的中文含義是“小甜餅”,是很小很小的檔案,它存儲在用戶端浏覽器的記憶體或者硬碟上。包含在HTTP請求封包中,并在伺服器中與浏覽器之間傳遞。但是這個也不是伺服器随意給浏覽器的,需要浏覽器使用Cookie為伺服器記錄一些資訊。

         舉個例子:把這個web伺服器比作一家商場,商場裡面的每個店面是一個web頁面,而Cookie就相當于你第一次進入這家商場的時候商場給你辦理的會員卡,但是會存儲你的姓名手機号類似的 ,就會允許你在每一個店裡享受優惠條件,隻要在會員卡有效時間内,你任何時間都可以來這家商場拿着你的會員卡,你就會被看作商場的會員。

        看一下Cookie具體的流程:

使用者第一次登陸輸入登陸的資訊(例如賬号密碼)然後請求伺服器進行登陸,第一次登陸驗證成功後。伺服器通過在 HTTP 響應封包中設定一個 Set-Cookie 字段,并把 Cookie 資料放在 Set-Cookie 字段中以HTTP 封包傳給浏覽器;

浏覽器在接收到 HTTP 響應封包後,檢查到 Set-Cookie 字段有值,會在本地建立一個 Cookie 檔案以鍵值對的形式來儲存資料;

當浏覽器再次向同一個伺服器發送請求其他腳本時,浏覽器會先搜尋本地儲存的 Cookie 檔案,如果在 Cookie 檔案中有任何與正在連接配接的 URL 相關的 Cookie,就在 HTTP 請求封包中設定一個 Cookie 字段,并把 Cookie 檔案中的資料添加到該字段中,最後把攜帶 Cookie 字段的 HTTP 請求封包發送給伺服器。

伺服器的每個腳本都可以接受Cookie的資料,并重新對登陸者的身份進行驗證,而不是每次使用者都需要重新去輸入登陸資訊。

(2)PHP如何設定Cookie

       PHP 透明地支援 HTTP Cookie。Cookie是一種在遠端浏覽器端儲存資料并以此來跟蹤和識别使用者的機制。可以用 setcookie() 或 setrawCookie() 函數來設定 Cookie。Cookie是 HTTP 标頭的一部分,是以 setCookie() 函數必須在其它資訊被輸出到浏覽器前調用,這和對 header() 函數的限制類似。可以使用輸出緩沖函數來延遲腳本的輸出,直到按需要設定好了所有的 cookie 或者其它HTTP頭。

setcookie()函數

PHP官網setcookie()函數解釋:
	https://www.php.net/manual/zh/function.setcookie.php
函數用法:
    setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] ) : bool
作用:
	一旦設定 Cookie 後,下次打開頁面時可以使用 $_COOKIE 讀取。
參數:
	$name	Cookie的識别名稱				  随後可以利用$_COOKIE['name']擷取對應value
	$value	Cookie的值,以數值或者字元串形态	這個值儲存于使用者的電腦裡,請勿儲存敏感資訊。
	$expire Cookie過期時間,以時間戳的形式 如果設定成零或者不寫 Cookie 會在會話結束時過期(也就是關掉浏覽器時)
	$path	Cookie有效的伺服器路徑, 預設值是設定 Cookie 時的目前目錄。
	$domain	Cookie所屬伺服器的域名
	$secure	指明Cookie是否在安全的https下傳遞
	$httponly Cookie 僅可通過 HTTP 協定通路
傳回值:
	如果在調用本函數以前就産生了輸出,setcookie() 會調用失敗并傳回 FALSE。 如果 setcookie() 成功運作,傳回 TRUE。
           

(3)設定Cookie并擷取Cookie

$name = 'Tacks';
#isset檢測變量是否已設定并且非 NULL 
if(!isset($_COOKIE['name'])){//第一次通路,浏覽器還不知道cookie有name 
    setcookie('name',$name);//設定cookie name='Tacks'
}else{//第二次通路頁面,浏覽器知道cookie有name
    echo $_COOKIE['name'];//通過$_COOKIE全局數組進行擷取對應的cookie值
}
           

 (4)設定過期時間

setcookie('name',$name,time()+60*60*24);//設定cookie name='Tacks'  過期時間一天
           

(5)設定儲存路徑

setcookie('name',$name,time()+60*60*24,'/php/');#設定其他目錄進行儲存
           

(6)可以看一下請求頭的一些資訊

       用戶端浏覽器第一次請求後,伺服器設定對應Cookie傳回攜帶到http請求頭中,再次傳回給用戶端,用戶端将其存儲在本地,下一次用戶端請求頁面的時候,就會攜帶Cookie的請求頭 。

(7)數組形态的Cookie

        通過帶 數組[]标記的 Cookie 名稱,也可以把 Cookie 設定成數組。 如果有數組元素,可以把它放進 Cookie 裡; 腳本接收到時,Cookie 名稱裡的值會是一個數組。

$admin['name']  = 'Tacks';
$admin['pass']  = '12a@#$yh%^&*009238,.y+00-8~86GADB"28\3/ad42';#這裡特殊符号比較多
$admin['power'] = 0;
#Cookie也可以利用多元數組的形式進行設定
setcookie('admin[name]',$admin['name']);
setcookie('admin[pass]',$admin['pass']);
setcookie('admin[power]',$admin['power']);
           

(8)擷取Cookie二維數組的值

#上面存儲admin二維數組擷取
foreach($_COOKIE['admin'] as $key=>$value){
    echo $key,":",$value,'<br/>';
}
/*
name:Tacks
pass:12a@#$yh%^&*009238,.y+00-8~86GADB"28\3/ad42
power:0
*/
           

(9)setrawcookie()函數

setrawcookie() 和 setcookie() 非常相似,唯一不同之處是發送到浏覽器的 cookie 值沒有自動經過 URL(urlencode)編碼。

(10)删除Cookie

           要删除一個 Cookie,應該設定過期時間為過去,以觸發浏覽器的删除機制。

setCookie('name','Tacks',time()-1);
           

二、Session

(1)工作原理

       Session技術與Cookie相似,都是用來存儲使用者的相關資料。但是最大的不同之處,在于Cookie是将資料存儲在用戶端中,而Session則是将資料存儲在伺服器系統下面。

      Session的中文含義是“會話”,在web系統中,通常指使用者與web系統進行互動的過程,也就是從使用者打開浏覽器登陸到web系統中,到關閉浏覽器退出web系統的這個過程。

      在Web發展曆史上,Cookie技術的出現确實是一個重大的改革,但是Cookie在存儲在用戶端中可以進行修改。不太安全,另外使用者如果篡改了,那麼伺服器也就不能正常追蹤某個使用者了。而Session技術是将使用者相關的資料放在伺服器下面,是以是相對安全的,使用者無法停用Session的使用。

       舉個例子:還是最上面那個商場的例子,使用者去過商場後,Cookie好比使用者自己存放一張會員卡在自己這裡,但是如果會員卡丢失,那麼就不能以會員方式進行購物了;而Session則是在使用者辦理卡的時候,由商場去記錄使用者的會員資訊,這樣下次使用者去商場不需要帶卡了,隻需要報一下你的手機号(唯一辨別符)或者會員卡号,商場就可以查到你的資訊,進而判斷你是否是會員。

      就這樣用戶端隻需要存儲由伺服器為使用者建立的一個Session辨別符(相當于會員卡号),稱之為SessionID,而在伺服器端存儲Session變量的值。SessionID是一個既不會重複又不容易找到規律的,由32位16進制數組成的字元串。SessionID是會儲存在用戶端的Cookie中。如果使用者阻止Cookie的使用,可以将SessionID儲存在使用者浏覽器位址URL中,當使用者請求web伺服器中,就會把SessionID發送給伺服器,伺服器再通過SessionID就可以提取儲存在伺服器中的Session變量,伺服器可以利用全局變量$_SESSION進行共享變量。 

       Session 的工作機制是:為每個訪客建立一個唯一的 id ( Session ID),并基于這個 Session ID 來存儲變量。SessionID存儲在 Cookie中,或者通過 URL 進行傳導。有兩種情況去傳送SessionID, Cookie 方式相對好一些,但是使用者可能在浏覽器中關閉 Cookie;第二種方案就是把SessionID直接并入到 URL 中,以保證SessionID 的傳送。無需開發人員幹預,PHP 就可以自動處理 URL 傳送SessionID 的場景。 如果啟用了 session.use_trans_sid 選項, PHP 将會自動在相對 URL中包含會話 ID。

看一下Session具體的流程:

當浏覽器第一次通路 PHP 腳本時,seesion_start() 函數會建立一個唯一的 Session ID(每個用戶端都有一個唯一的辨別),并自動通過 HTTP 的響應頭,将這個 Session ID 儲存到用戶端 Cookie 中。同時,也在伺服器端建立一個以 Session ID 命名的檔案,用于儲存這個使用者的會話資訊;

當同一個使用者再次通路這個網站時,會自動通過 HTTP 的請求頭将 Cookie 中儲存的 Seesion ID 再攜帶過來;

伺服器 PHP 腳本接受到用戶端請求,這時 session_start() 函數就不會再去配置設定一個新的 Session ID,而是在伺服器的硬碟中去尋找和這個 Session ID 同名的 Session 檔案,将這之前為這個使用者儲存的會話資訊讀出。

(2)PHP設定Session與讀取Session

Session的設定不同于Cookie,必須先進行啟動。調用session_start()函數,以便讓PHP的核心程式和Session相關的内建環境變量預先載入記憶體。session_start()函數作用啟動新會話或者重用現有會話。

        基于Cookie的Session,在開啟前不能有任何輸出内容,因為此函數有設定頭資訊的内容。如果不想每次都進行session_start()開啟,可以在php.ini裡面設定“session.auto_start=1”。但是對象不能放入Session中,因為類定義要在session_start()開啟前進行加載。

       另外可以通過$_SESSION超全局數組,進行指派設定。執行下面代碼後,預設情況下,PHP.ini 中設定的 SESSION 儲存方式是 files(session.save_handler = files),即使用讀寫檔案的方式儲存 SESSION 資料,Session變量就會存儲在伺服器下的某個檔案中,該檔案的位置是通過php.ini中session.save_path屬性指定的路徑。

 執行後它會在服務端對應的存儲目錄下,生成一個以sess_後面跟着sessionID的檔案。内容大緻是"變量名|類型:長度:值;"的形式。另外在用戶端可以看到下面會存儲Cookie,其預設是PHPSESSID,值的内容就是存儲的SessionID。

(3)銷毀變量與銷毀Session

如果您希望删除某些 session 資料,可以使用 unset() 或 session_destroy() 函數。例如使用者向退出web系統,就需要提供一個登出功能。切記不要用unset($SESSION)登出整個Session數組,這樣就不能通過($SESSION)超全局注冊變量。

(4)Session的登出過程

PHP預設的Session是基于Cookie的,SessionID被伺服器存儲在用戶端的Cookie中,是以在登出Session時也需要清除Cookie中儲存的SessionID,而這就需要借助setCookie()函數完成。删除儲存在用戶端Cookie中的SessionID。進而銷毀關于本次會話的所有相關資源。

      另外在PHP腳本中,可以通過調用session_name()函數擷取Session名稱, 如果指定name參數, session_name() 函數會更新會話名稱, 并傳回原來的會話名稱。

(5)Session的垃圾自動回收機制

上面的四步走之後可以銷毀本地會話,但是使用者如果不直接點選退出,而是關閉浏覽器。那麼在伺服器端的Session是不會被删除的,如果下次進行登陸,又會重新配置設定一個SessionID進行登陸,這個是因為在php.ini檔案中預設設定session.cookie_lifetime=0,來進行設定SessionID在用戶端Cookie 有效期,0指的是直到浏覽器關閉。如果你設定的有效期(以秒為機關),那麼不管你是否關閉浏覽器,隻要在有效期後,SessionID就會消失,進而用戶端的SessionID也沒有了,但是這個時候伺服器的Session并沒有删除,如果這樣的垃圾檔案越來越多,會影響伺服器系統造成負荷,是以系統必須必須要有一種機制進行删除。

       設定Session後,伺服器生成的Session檔案就是一個小小的文本檔案,是檔案就會有一個修改時間的屬性。那麼垃圾回收機制就是根據這個時間來進行判斷的。通過php.ini中設定session.gc_maxlifetime選項來設定一個時間(以秒為機關)。例如該選項的值是3600,那麼系統垃圾回收程式,就會在所有的Session檔案中進行排查,如果有檔案的修改時間距離目前系統時間大于3600秒,就會将其删除,是以失去了用戶端SessionID引用的檔案,那麼就通路不到該變量;同樣如果沒有失去用戶端SeesionID的檔案,隻要使用者在使用,那麼Session檔案修改時間就會更新,進而不會被删除。

      垃圾回收機制也是在開啟session_start()時候啟動的,但是有一個問題,一個網站的使用者登陸多了,可能會多次調用session_start()開啟會話,這樣垃圾回收機制可能總是被調用,那麼樣就不是很合理,一天請求太頻繁了。可以通過在php.ini裡面設定session.gc_probaility和session.gc_divisor兩個選項,進行設定啟動回收程式的機率,計算公式大概是"session.gc_probaility/session.gc_divisor"。是以一般設定session.gc_probaility=1,選項session.gc_divisor=100,也就是調用session_start()函數開啟會話100次才可能啟動一次垃圾回收程式。會話請求越頻繁,機率值應當越小。

(6)傳遞SessionID

通過上面的了解,我們知道用戶端與伺服器通過SessionID進行追蹤一個使用者,那麼這個SessionID的傳遞方式有兩種,預設是基于Cookie進行傳遞,另一種通過URL進行傳遞SessionID。

     如果用戶端沒有禁用Cookie,那麼在PHP腳本中通過session_start()函數進行初始化,伺服器會通過發送HTTP中會攜帶SessionID,用戶端會響應到然後将其儲存在浏覽器Cookie中。

      如果禁用Cookie,那麼浏覽器中也就不會儲存其SessionID,因而下次去請求伺服器的時候,請求頭中不會包含SessionID的資訊,而伺服器調用session_start()又會重新建立一個會話,這樣就無法追蹤使用者狀态。

     PHP中另一種傳遞會話ID機制,就是通過重寫用戶端請求的URL,把SessionID添加到URL中,這樣服務端也可以接受到。無需開發人員幹預,PHP 就可以自動處理 URL 傳送會話 ID 的場景。 如果啟用了 session.use_trans_sid 選項, PHP 将會自動在相對 URI 中包含會話 ID。詳情可以看一下PHP官網對傳遞會話ID的方式。

三、Cookie與Session的差別

1.存放位置:

Cookie放在用戶端浏覽器中;

Session放在伺服器端某個檔案夾下;

2.存放的類型:

Cookie隻能存放字元串。

Session還可以存放對象等其他類型。

3.存放大小:

Cookie存儲的資料根據浏覽器的不同而有不同的限制,Chrome大概是50左右,最大4097位元組。

Session預設沒有限制,但是如果過多的話,會影響伺服器性能。

4.存放路徑:

Cookie是可以用setcookie()函數設定路徑參數的,如果同一個網站下不同路徑的Cookie互相也是通路不到。

Session不能區分路徑,同一個使用者在會話期間,Session在任何一個地方都可以通路到。

5.生命周期:

Cookie是可以用setcookie()函數過期時間的,如果浏覽器關閉,Cookie還沒過期那麼會存儲到本地,下次打開浏覽器的時候還有。如果沒有設定過期時間一般是到浏覽器關閉的時候就銷毀了。

Session預設基于Cookie,然後預設設定session.cookie_lifetime=0也就是浏覽器關閉的時候,會删除用戶端Cookie,那麼你就通路不到你之前的會話,而是新建立一個會話,但是遠端伺服器上的會話檔案不會被删除(它會被垃圾回收機制進行處理);另外Session也可以用session.cookie_lifetime進行設定SessionID在用戶端Cookie 有效期。

6.浏覽器通路:

Cookie可以在不同浏覽器下共享資料,都能通路到Cookie的資訊。

Session隻能在一個浏覽器獨享,常見的場景就是你如果登陸一個web系統後,複制連結到另一個浏覽器上是需要重新進行登陸建立新的會話。

7.建立方式:

Cookie直接就可以用setcookie()進行設定。

Session必須先開啟session_start(),然後用超全局變量$_SESSION['name'] = 'Tacks';進行設定。

8.手動銷毀

Cookie利用 setCookie('name','Tacks',time()-1);設定過期就好了。

Session需要四步走,開啟session_start(),然後删除對應的session變量$_SESSION = [];,然後讓對應用戶端的cookie也過期,然後徹底消除會話session_destroy();

9.用處

Cookie一般用于不重要的資料存儲在浏覽器上,如果想要更安全一些,可以利用一些加密算法處理後存放。

Session一般于登陸時候,存儲會話狀态。

繼續閱讀