面試-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一般於登陸時候,存儲會話狀態。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章