PHP中的會話服務使用

前言

我們都知道Web實現是基於HTTP協議的,而HTTP協議是無狀態的。即服務器只會給客戶端請求提供服務,不會記錄用戶上一次的行爲,那麼就是說如果用戶在第一次做過登錄的操作,那麼用戶第二次操作的時候服務器不會認爲當前請求是上一個用戶的操作而是認爲是不同用戶的請求,每一次都需要登錄,這樣用戶的體驗感極差,那麼怎麼解決這個問題呢?會話服務就很好的解決了這個問題( Cookie | Session )

一丶Cookie的使用

Cookie 是HTTP協議下,服務器或腳本可以維護客戶信息的一種方式,用戶在瀏覽器上的一個很小的文本文件。【常用來記憶 用戶名、密碼、個性化設置、個人偏好記錄等等】
Cookie 保存在客戶端(用戶瀏覽器),可以手動刪除。如果瀏覽器上的Cookie 太多,超過了系統所允許的範圍(通常限制爲50個,每個不超過4kb),瀏覽器會自動刪除。

1.使用setcookie函數創建Cookie

setcookie('name','張三');

如何才能知道是否創建成功?F12 或右鍵檢查,查看【Application】=>【Storage】=>[Cookies].查看是否有剛剛創建的Cookie 信息

2.設置Cookie的有效時間

如上,成功創建了Cookie ,但是我們關閉瀏覽器,再訪問相同地址的URL,再次查看Application裏的Cookie 發現:Cookie 已經失效了。所以我們知道如上創建的Cookie ,默認關閉瀏覽器就會失效。現在我用setcookie的第三個參數來設置有效時間,設置格式:

setcookie(key,value,time()+3600)   //有效時間3600秒

要刪除一個Cookie

應該設置過期時間爲過去,以觸發瀏覽器的刪除機制

setcookie("name", "張三", time()-3600);

3.Cookie的作用路徑範圍

根目錄(/---- x
          ----- b.php
      ---- a.php

Cookie 的有效路徑範圍,默認的路徑值是 Cookie 所處的當前目錄,如圖的目錄結構,a.php創建的Cookie ,默認的作用範圍,所以b.php能訪問到, 然後b.php創建的Cookie 作用範圍/x,故a.php不能訪問。

setcookie(key,value,time()+3600,'/')   //Cookie 將在整個域名內有效

4.Cookie的作用的有效域名

如果我們在www.study.com域名下設置Cookie ,默認的這個cCookie ookie僅在 www 這個二級域名中有效。如果此時還有一個二級域名moblie.study.com想要和www進行共享Cookie ,我們 只需如下配置第5個參數

setcookie(key,value,time()+3600,'/','study.com') 

設置成子域名(例如 ‘www.example.com’),會使 Cookie 對這個子域名和它的三級域名有效(例如 w2.www.example.com)。 要讓 Cookie 對整個域名有效(包括它的全部子域名),只要設置成域名就可以了(這個例子裏是 ‘example.com’)

5.Cookie 與安全的HTTPS

默認值:false;設置這個 Cookie 是否僅僅通過安全的 HTTPS 連接傳給客戶端,設置成 true 時,只有安全連接存在時纔會設置 Cookie。 如果是在服務器端處理這個需求, 我們需要僅僅在安全連接上發送此類 Cookie (可以通過 $_SERVER[“HTTPS”] 判斷)

6.Cookie的JavaScript訪問

默認值:false; 如果我們設置true; Cookie 即僅可通過 HTTP 協議訪問。 這意思就是 Cookie 無法通過類似 JavaScript 這樣的腳本語言訪問。

7.Cookie的工作原理

在這裏插入圖片描述
結合上圖說:當用戶初次對服務器發起請求時(1),服務器會執行對應的腳本,比如demo.php文件,執行setcookie函數(2)

# demo.php
setcookie('name','niege',time()+3600);

然後服務器會在響應消息的時候在響應頭裏添加Set-Cookie信息,將信息Cookie 的形式發送給瀏覽器(3)。 如果瀏覽器沒有禁用Cookie ,便會接受了服務器發送的Cookie 信息,就會將它保存在瀏覽器的緩衝區中(4)。 這樣當瀏覽器繼續訪問該服務器,都會攜帶Cookie 發送給服務器(5),從而使服務器分辨出當時請求是由那個用戶發出的(6)

8.使用Cookie注意需要主要幾個點

  • cookie被附加在每個http請求響應中,無形中增加了數據流量

  • cookie在http請求中是明文傳輸的,所以安全性不高,容易被竊取

  • cookie是來自瀏覽器的數據,可以被篡改,因此服務器接收後必須驗證數據的合法性

  • 瀏覽器限制cookie的數量和大小,chrome數量在50左右,每個不超過4kb,但是在測試-版本 71.0.3578.98(正式版本)可以創建168個

二丶Session的使用

1.Session的工作原理

當第一次訪問網站時,Seesion_start()函數就會創建一個唯一的Session ID,並自動通過HTTP的響應頭,將這個Session ID保存到客戶端Cookie中。同時,也在服務器端創建一個以Session ID命名的文件,用於保存這個用戶的會話信息。當同一個用戶再次訪問這個網站時,也會自動通過HTTP的請求頭將Cookie中保存的Seesion ID再攜帶過來,這時Session_start()函數就不會再去分配一個新的Session ID,而是在服務器的硬盤中去尋找和這個Session ID同名的Session文件,將這之前爲這個用戶保存的會話信息讀出,在當前腳本中應用,達到跟蹤這個用戶的目的。 Session以數組的形式使用,如:$_SESSION['session名']

2.Session初始化

Session的設置不同於Cookie,必須先啓動,在PHP中必須調session_start() ,函數的語法格式如下:

session_start ([ array $options = array() ] ) : bool 

session_start() 會創建新會話或者重用現有會話。 如果通過 GET 或者 POST 方式,或者使用 cookie 提交了會話 ID, 則會重用現有會話

注意session_start()函數之前不能有任何輸出

3.註冊一個會話變量和讀取Session

在PHP中使用Session變量,除了要啓動之外,還要經過註冊的過程。註冊和讀取Session變量,都要通過訪問$_SESSION數組完成。在$_SESSION關聯數組中的鍵名具有和PHP中普通變量相同的命名規則。註冊Session變量的代碼如下所示:

<?php
//啓動session的初始化
session_start();
//註冊session變量,賦值爲一個用戶的名稱
$_SESSION["username"] = "skygao";
//註冊session變量,賦值爲一個用戶的ID
$_SESSION["uid"] = 1;
?>

執行該腳本後,兩個Session變量就會被保存在服務器端的某個文件中,該文件的位置是通過php.ini文件,在session.save_path屬性指定的目錄下

4.註銷變量與銷燬Session

當使用完一個Session變量後,可以將其刪除,當完成一個會話後,也可以將其銷燬。如果用戶退出Web系統,就需要爲他提供一個註銷的功能,把他的所有信息在服務器中銷燬。銷燬和當前Session有關的所有的資料,可以調用session_destroy()函數結束當前的會話,並清空會話中的所有資源。該函數的語法格式如下所示:

 session_destroy ( void ) : bool//銷燬和當前Session有關的所有資料

該函數並不會釋放和當前Session相關的變量,也不會刪除保存在客戶端Cookie中的SessionID。因爲$_SESSION數組和自定義的數組在使用上是相同的,所以我們可以使用unset()函數來釋放在Session中註冊的單個變量。如下所示:

unset($_SESSION['鍵名']);

一定要注意,不要使用unset($_SESSION)刪除整個$_SESSION數組,這樣將不能再通過$_SESSION超全局數組註冊變量了。但如果想把某個用戶在Session中註冊的所有變量都刪除,可以直接將數組變量$_SESSION賦上一個空數組。如下所示:

 $_SESSION = array();

PHP默認的Session是基於Cookie的,SessionID被服務器存儲在客戶端的Cookie中,所以在註銷Session時也需要清除Cookie中保存的SessionID,而這就必須藉助setcookie()函數完成。在PHP腳本中,可以通過調用session_name()函數獲取Session名稱。刪除保存在客戶端Cookie中的SessionID,代碼如下所示:

<?php
//判斷Cookie中是否存在session ID
if(isset($_COOKIE[session_name()]))
{
    //刪除包含Session ID的cookie,注意第四個參數一定要和php.ini設置的路徑相同
    setcookie(session_name(),'',time()-3600,'/');
}
?>

通過前面的介紹可以總結出,Session的註銷過程共需要4個步驟。在下例中,提供完整的四個步驟代碼,運行該腳本就可以關閉Session,並銷燬與本次會話有關的所有資源。代碼如下所示:

<?php
//第一步:開啓Session並初始化
session_start();

//第二部:刪除所有Session的變量,也可以用unset($_SESSION[XXX])逐個刪除
$_SESSION = array();

//第三部:如果使用基於Cookie的session,使用setCookkie()刪除包含Session ID的cookie
if(isset($_COOKIE[session_name()])) 
{
    setCookie(session_name(), "", time()-42000, "/");
}

//第四部:最後徹底銷燬session
session_destroy();

?>

5.Session的垃圾自動回收機制

可以通過session_destroy()函數在頁面中提供一個“退出”按鈕,通過單擊銷燬本次會話。但如果用戶沒有單擊退出按鈕,而是直接關閉瀏覽器,或斷網等情況,在服務器端保存的Session文件是不會刪除的。雖然關閉瀏覽器,下次需要重新分配一個新的Session ID重新登錄,但這只是因爲在php.ini中的設置seesion.cookie_lifetime = 0,來設定Session ID在客戶端Cookie中的有效限期,以秒爲單位指定了發送到瀏覽器的Cookie的生命週期。當系統賦予Session有效期限後不管瀏覽器是否開啓,Session ID都會自動消失。而客戶端Session ID消失服務器端保存的Session文件並沒有被刪除。所以沒有被Sessoin ID引用的服務器端Session文件,就成爲了“垃圾”。

服務器保存的Session文件就是一個普通文本文件,所以都會有文件修改時間。“垃圾回收程序”啓動後就是根據Session文件的修改時間,將所有過期的Session文件全部刪除。通過在php.ini中設置session.gc_maxlifetime選項來指定一個時間(單位:秒),例如設置該選項值爲1440(24分鐘)。“垃圾回收程序”就會在所有Session文件中排查,如果有修改時間距離當前系統時間大於1440秒的就將其刪除。

session垃圾回收程序是怎樣的啓動機制呢?垃圾回收程序是在調用session_start()函數時啓動的。而一個網站有多個腳本,沒有腳本又都要使用session_start()函數開啓會話,又會有很多個用戶同時訪問,這就很可能session_start()函數在1秒內被調用N次,而如果每次都會啓動Session垃圾回收程序,這樣是很不合理的。可以通過php.ini文件中修改session.gc_probabilitysession.gc_divisor兩個選項,設置啓動垃圾回收程序的概率。會根據session.gc_probability/session.gc_divisor公示計算概率,例如選項session.gc_probability=1,而選項session.gc_divisor=100,這樣的概率就是1/100,即session_start()函數被調用100次纔會有一次可能啓動垃圾回收程序

6.Session的php.ini配置選項

配置名稱 說明
session.auto_start = 0 ; 在請求啓動時初始化session
session.cache_expire = 180 ; 設置緩存中的會話文檔在 n 分鐘後過時
session.cookie_lifetime = 0 ; 設置按秒記的cookie的保存時間,相當於設置Session的過期時間,爲0時表示直到瀏覽器被重啓
session.auto_start = 1; 這樣就無需每次使用session之前都要調用session_start()不建議使用.但啓用該選項也有一些限制,如果確實啓用了 session.auto_start,則不能將對象放入會話中,因爲類定義必須在啓動會話之前加載以在會話中重建對象
session.cookie_path = / ; cookie的有效路徑
session.cookie_domain = ; cookie的有效域
session.name = PHPSESSID; 用在cookie裏的session的名字
session.save_handler = files ; 用於保存/取回數據的控制方式
session.save_path = /tmp ; 在 save_handler 設爲文件時傳給控制器的參數, 這是數據文件將保存的路徑
session.use_cookies = 1 ; 是否使用cookies
session.cookie_lifetime=0; 關閉瀏覽器相應的cookie文件即被刪除
session.gc_maxlifetime; 設置過期session時間,默認1440秒(24分鐘)
session.gc_probability/session.gc_divisor; 啓動垃圾回收機制的概率(建議值爲1/1000——5000)

7.Cookie禁用時通過URL傳遞Session的ID

使用Session跟蹤一個用戶,是通過在各個頁面之間傳遞唯一的Session ID,並通過Session ID提取這個用戶在服務器中保存的Session變量。常見的Session ID傳送方法有以下兩種。

第一種方法是基於cookie的方式傳遞session ID,這種方式更優,但不總是可用, 因爲用戶在客戶端可以屏蔽cokie;

第二種方法是通過url參數進行傳遞,直接將session ID嵌入到URL中去。

在Session的實現中通常都是採用Cookie的方式,客戶端保存的Session ID就是一個Cookie。當客戶禁用Cookie時,Session ID就不能在Cookie中保存,也就不能在頁面之間傳遞,此時Session失效。不過PHP5在Linux平臺可以自動檢查Cookie狀態,如果客戶端禁用它,則系統自動把Session ID附加到URL上傳送。而使用Windows系統作爲Web服務器則無此功能。

在PHP中提出了跟蹤Session的另一種機制,如果客戶瀏覽器不支持Cookie,則PHP可以重寫客戶請求的URL,把Session ID添加到URL信息中。可以手動地在每個超鏈接的URL中都加上一個Session ID,但工作量比較大,不建議使用這種方法。如下所示:

<?php
//開啓session
session_start();

//在每個URL後面附加上參數,變量名爲session_name()獲取名稱,值通過session_id()獲取
echo '<a href="demo.php?'.session_name().'='.session_id().'">連接演示</a>';
?>

在使用Linux系統做服務器時,則在編輯PHP時如果使用了–enable-trans-sid配置選項,和運行時選項session.use_trans_sid都被激活,在客戶端禁用Cookie時,相對URL將被自動修改爲包含會話ID。如果沒有這麼配置,或者使用Windows系統作爲服務器時,可以使用常量SID。該常量在會話啓動時被定義,如果客戶端沒有發送適當的會話Cookie,則SID的格式爲session_name = session_id,否則就爲一個空字符串。因此可以無條件地將其嵌入到URL中去。在下例中使用兩個腳本程序,演示了Session ID的傳送方法。

<?php
session_start();

$_SESSION["username"] = "admin";

echo "session ID:".session_id()."<br>";

?>

三丶 Cookie 與 Session的區別

1.數據存放位置不同

Cookie數據存放在客戶的瀏覽器上,Session數據放在服務器上

2.安全程度不同

Cookie不是很安全,別人可以分析存放在本地的COOKIE並進行COOKIE欺騙,考慮到安全應當使用Session

3.性能使用程度不同

Session會在一定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用Cookie

4.數據存儲大小不同

單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個Cookie,而Cession則存儲與服務端,瀏覽器對其沒有限制

5.會話機制不同

Session會話機制:Session會話機制是一種服務器端機制,它使用類似於哈希表(可能還有哈希表)的結構來保存信息

cookies會話機制:Cookie是服務器存儲在本地計算機上的小塊文本,並隨每個請求發送到同一服務器。 Web服務器使用HTTP標頭將Cookie發送到客戶端。在客戶端終端,瀏覽器解析Cookie並將其保存爲本地文件,該文件自動將來自同一服務器的任何請求綁定到這些Cookie

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