跳轉到內容

PHP 程式設計/會話

來自華夏公益教科書,開放的書,開放的世界

會話允許 PHP 指令碼在 Web 伺服器上儲存資料,這些資料可以在以後使用,即使在對不同 PHP 頁面請求之間也是如此。每個會話都有一個不同的識別符號,它作為 cookie 或 $_GET 變數傳送到客戶端的瀏覽器。會話在使用者關閉瀏覽器時、Web 伺服器刪除會話資訊時或程式設計師顯式銷燬會話時結束。在 PHP 中,它通常稱為 PHPSESSID。會話對於保護使用者無法讀取或寫入的資料非常有用,尤其是在 PHP 開發人員不希望在 cookie 中提供資訊的情況下,因為它們很容易被讀取。會話可以透過 $_SESSION 超全域性變數來控制。儲存在此陣列中的資料在整個會話期間保持永續性。它是一個簡單的陣列。會話比 cookie 更易於使用,這為 PHP 開發人員提供了很大幫助。通常,會話用於使用者登入、購物車和其他需要保持瀏覽流暢的補充。PHP 指令碼可以輕鬆控制正在傳送的會話 cookie,並控制整個會話資料。會話始終儲存在一個唯一的檔名中,要麼在臨時資料夾中,要麼在特定資料夾中,如果指令碼指示這樣做。

使用會話

[編輯 | 編輯原始碼]

在每個將成為當前會話一部分的 PHP 指令碼的頂部,必須使用 session_start() 函式。它必須在第一個輸出(echo 或其他)之前,否則會導致錯誤“Headers already sent out”。

 session_start();

此函式將執行以下操作

  1. 它將檢查 _COOKIE_GET 資料,如果已給出
  2. 如果會話檔案在 session.save_path 位置不存在,它將
    1. 生成一個新的唯一識別符號,並且
    2. 基於該識別符號建立一個新檔案,並且
    3. 將一個 cookie 傳送到客戶端的瀏覽器
  3. 如果它確實存在,PHP 指令碼將嘗試將檔案的資料儲存到 _SESSION 變數中,以供進一步使用

現在,您可以透過兩種不同的方式簡單地設定變數,預設方法

 $_SESSION['example'] = "Test";

或過時的使用方法

 $example="Test";
 session_register($example);

以上兩個語句都將註冊會話變數 $_SESSION['example'] 作為“Test”。過時的使用方法不應使用,僅列出是因為您仍然可以在由不知道新方法的程式設計師編寫的指令碼中看到它。建議使用預設方法。

會話配置選項

[編輯 | 編輯原始碼]

PHP 會話很容易控制,並且可以透過一些小的因素變得更加安全或不太安全。以下是一些可以使用 php_ini() 函式輕鬆更改的執行時選項

名稱 預設值 可更改
session.save_path "/tmp" PHP_INI_ALL
session.name "PHPSESSID" PHP_INI_ALL
session.save_handler "files" PHP_INI_ALL
session.auto_start "0" PHP_INI_ALL
session.gc_probability "1" PHP_INI_ALL
session.gc_divisor "100" PHP_INI_ALL
session.gc_maxlifetime "1440" PHP_INI_ALL
session.serialize_handler "php" PHP_INI_ALL
session.cookie_lifetime "0" PHP_INI_ALL
session.cookie_path "/" PHP_INI_ALL
session.cookie_domain "" PHP_INI_ALL
session.cookie_secure "" PHP_INI_ALL
session.use_cookies "1" PHP_INI_ALL
session.use_only_cookies "0" PHP_INI_ALL
session.referer_check "" PHP_INI_ALL
session.entropy_file "" PHP_INI_ALL
session.entropy_length "0" PHP_INI_ALL
session.cache_limiter "nocache" PHP_INI_ALL
session.cache_expire "180" PHP_INI_ALL
session.use_trans_sid "0" PHP_INI_SYSTEM/PHP_INI_PERDIR
session.bug_compat_42 "1" PHP_INI_ALL
session.bug_compat_warn "1" PHP_INI_ALL
session.hash_function "0" PHP_INI_ALL
session.hash_bits_per_character "4" PHP_INI_ALL
url_rewriter.tags "a=href,area=href,frame=src,input=src,form=fakeentry" PHP_INI_ALL

這段程式碼就是一個簡單的例子

 //Setting The Session Saving path to "sessions", '''must be protected from reading'''
 session_save_path("sessions"); // This function is an alternative to ini_set("session.save_path","sessions");
 //Session Cookie's Lifetime ( not effective, but use! )
 ini_set("session.cookie_lifetime",time()+60*60*24*500);
 //Change the Session Name from PHPSESSID to SessionID
 session_name("SessionID");
 //Start The session
 session_start();
 //Set a session cookie ( Required for some browsers, as settings that had been done before are not very effective 
 setcookie(session_name(), session_id(), time()+3600*24*365, "/");

此示例只是將 cookie 設定為下一年。

結束會話

[編輯 | 編輯原始碼]

當用戶單擊“登出”或“退出”時,您通常希望銷燬所有登入資料,以便任何人都無法再訪問它。會話檔案將被簡單地刪除,並且 cookie 將被取消設定

 session_destroy();

使用其他型別會話資料

[編輯 | 編輯原始碼]

諸如整數、字串和陣列之類的簡單資料可以輕鬆地儲存在 $_SESSION 超全域性陣列中,並從一個頁面傳遞到另一個頁面。但在嘗試透過賦值儲存物件的狀

避免會話固定

[編輯 | 編輯原始碼]

會話固定描述了一種攻擊向量,其中惡意第三方設定(即固定)使用者的會話識別符號 (SID),因此能夠訪問該使用者的會話。在如上所述的會話的基本實現中,這

  1. 不要使用 GET 或 POST 變數來儲存會話 ID(在大多數 PHP 配置中,cookie 用於儲存 SID,因此程式設計師不需要執行任何操作來實現此功能);
  2. 在每次使用者請求時重新生成 SID(在會話開始時使用 session_regenerate_id());
  3. 使用會話超時:對於每個使用者請求,儲存當前時間戳,並在下次請求時檢查是否已超過超時間隔;
  4. 提供登出功能;
  5. 在每次請求時檢查“瀏覽器指紋”。這是一個儲存在 $_SESSION 變數中的雜湊,包含使用者代理標頭、客戶端 IP 地址、鹽值和/或其他資訊的組合。有關此
  6. 檢查來源:這並不適用於所有系統,但如果您知道您網站的使用者必須來自某個已知域,那麼您可以丟棄與來自其他地方的使用者相關的會話。它依賴於使用者代理提
此示例程式碼解決了上述所有要點,除了來源檢查。
$timeout = 3 * 60; // 3 minutes
$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']);
session_start();
if ( (isset($_SESSION['last_active']) && (time() > ($_SESSION['last_active']+$timeout)))
     || (isset($_SESSION['fingerprint']) && $_SESSION['fingerprint']!=$fingerprint)
     || isset($_GET['logout']) ) {
    do_logout();
}
session_regenerate_id(); 
$_SESSION['last_active'] = time();
$_SESSION['fingerprint'] = $fingerprint;
do_logout() 函式銷燬會話資料並取消設定會話 cookie。


華夏公益教科書