PHP Session原理分析及使用
之前在一個叫魔法實驗室的部落格中看過一篇《php session原理徹底分析》的文章,作者從session的使用角度很好闡述了在代碼運行過程中,每個環節的變化以及相關參數的設定及作用。本來想把原文轉帖過來,但是原部落格被關閉了。不知是這次大範圍的重新備案,還是其他什麼原因所致。透過百度快照找到一些原文資料,沒找到的將按先前的理解重新整理,以使大家對session能有更多了解。
楔子:Session大白話
Session,英文翻譯為“會話”,兩個人聊天,從第一句問好,到最後一句再見,這就構成了一個會話。 PHP裡的session主要是指客戶端瀏覽器與服務端資料交換的對話,從瀏覽器開啟到關閉,一個最簡單的會話週期。電腦語言一般怎麼實作會話呢?舉個通俗的例子:
服務端好比一個理髮店,客戶端好比每一個去理髮的客人,很多理髮店都有這種促銷手段,連續消費10次的客人,可以免費一次,大概有三種方式來實現:
1、理髮師傅記性太好,你來過幾次,他看一眼就知道——這叫協議本身支持會話;
2、每個客人發一個會員卡,你每次消費,都要帶著這張卡片,消費一次記錄一筆,當然還要加蓋印章——這叫透過cookie實現會話,缺點是安全性不高,我完全可以偽造會員卡或者公章;
3、理髮店準備一個大帳本,客人每人對應一個會員號碼或自己的個人資料,甚至密碼,每個客人來消費,報一下自己的會員號,再把消費次數記錄到大帳本裡——這就是session實現會話,客人腦中的會員號碼就是保存在客戶端的SESSIONID,大帳本就是保存在服務端的session數據,這樣相比第二種方法,安全性要高很多,除非你說你把自己的會員號碼和密碼都搞丟了,這叫做偽造客戶端的SESSIONID。
因為http協定是無狀態的,所以php要實作會話只能透過後面兩種方式,前一種cookie,缺點已經說了,安全性不高,所以重要的會話會選擇使用session。 session會話必須依靠一個標識,也可以理解成一個暗號,就是SESSIONID。這是個經過加密的串,保存在客戶端,通常在cookie裡,客戶端與服務端的每次交流都是透過這個SESSIONID,客戶端先自報家門,伺服器才能找到你在服務端保存的會話數據,繼續通話。
php.ini常用session設定
[服務端]
session.save_handler = files
預設為file,定義session在服務端的保存方式,file意為把sesion保存到一個臨時檔案裡,如果我們想自訂別的方式保存(例如用資料庫),則需要把該項目設定為user;
session.save_path = "/tmp/"
定義服務端儲存session的暫存檔案的位置。
session.auto_start = 0
如置1,則不用在每個檔案裡寫session_start(); session自動start。
session.gc_probability = 1
session.gc_divisor = 100
session.gc_maxlifetime = 1440
這三個配置組合構建服務端session的垃圾回收機制.gc_probability與dision.gsession 構成的執行理論,構成gsesc_prob解釋為服務端定期有一定的機率呼叫gc函數來對session進行清理,清理的機率為:gc_probability/gc_divisor 例如:1/100 表示每一個新會話初始化時,有1%的機率會啟動垃圾回收程序,清理的標準為session.gc_maxlifetime定義的時間。
[客戶端]
session.use_cookies = 1
sessionid在客戶端採用的儲存方式,置1代表使用cookie記錄客戶端的sessionid,同時,$_COOKIE變數裡才會有$_COOKIE['PHPSESSIONID']這個元素存在;
session.use_only_cookies = 1
也是定義sessionid在客戶端採用的儲存方式,置1代表僅使用cookie 來存放會話ID。一般來說,現在客戶端都會支援cookie,所以建議設定成1,這樣可以防止有關透過 URL 傳遞會話 ID 的攻擊。
session.use_trans_sid = 0
相對應於上面那個設置,這裡如果置1,則代表允許sessionid透過url參數傳遞,同理,建議設定成0;
session.referer_check =s
= 1的時候才會生效,目的是檢查HTTP頭中的"Referer"以判斷包含於URL中的會話id是否有效,HTTP_REFERER必須包含這個參數指定的字串,否則URL中的會話id將被視為無效。所以一般預設為空,即不檢查。
session.name = PHPSESSID
定義sessionid的名稱,即變數名,透過瀏覽器http工具可以查看PHPSESSID的值;
session.hash_function = 0
選擇session_name的加密方式,0代表md5加密,1代表sha1加密,預設是0,但是據說用sha1方式加密,安全性更高;
session.hash_bits_per_character = 4
指定在session_namename字串中的每個字元內保存多少位二進制數,這些二進制數是hash函數的運算結果。
4 bits: 0-9, a-f
5 bits: 0-9, a-v
6
url_rewriter.tags = "a=href,area= href,frame=src,input=src,form=,fieldset="
指定重寫哪些HTML標籤來包含sid(session_id)(僅在"session.use_trans_sid"開啟的情況下有效),URL重寫器將會加入一個隱藏的"",它包含了本應額外追加到URL上的信息。
session.cookie_lifetime = 0
保存sessionid的cookie檔案的生命週期,如置0,代表會話結束,則sessionid就自動消失,常見的強行關閉瀏覽器,就會遺失上一次的sessionid;
session. cookie_path = /
保存sessionid的cookie檔案在客戶端的位置;
session.cookie_domain = /
保存sessionid的cookie的網域設置,這跟cookie允許的網域的權限設定有關,一般來說想讓自己網站所有的目錄都能存取到客戶端的cookie,就應該設定成「/」如需要詳細了解,可以看下setcookie()函數的domain參數相關設定和使用方法;
session.bug_compat_42 = 1
session.bug_compat_warn = 1
這兩個可以說幾乎是快要被廢棄的設置,是為了老版本的php服務的,主要是針對session_register函數,因為php5的register_global預設是關閉狀態,所以在php5裡根本用不到session_register這個函數;而且php6就要廢除這個設置,直接定義為關閉,所以沒必要研究這兩個了;
session_start()做了些什麼?
假設php.ini中session的幾個關鍵參數配置為:
session.save_handler = files
session.use_cookies = 1
session.name = PHPSESSIDsession.save_path = "/tmp/"程式碼範例闡述,在一個會話過程中session_start的作用。
程式1:
session_start();
$_SESSION['uname'] = 'monkey';
$_SESSION['ukey'] = 20119999;>
? ()會做兩件事:
1、在客戶端產生一個存放PHPSESSID的cookie文件,這個文件的存放位置和存放方式跟程式的執行方式有關,不同的瀏覽器也不盡相同,這一步會產生一個序列化後的字串-PHPSESSID;查看瀏覽器中的cookie訊息,可以安裝相關插件。 firefox中httpfox,web developer等都是很好的工具。
2、在服務端產生一個存放session資料的暫存文件,存放的位置由session.save_path參數指定,名稱類似“sess_85891d6a81ab13965d349bde29b2306c”,“sess1ab13965d349bde29b2306c”,“sess_v. 6c」即此次會話的PHPSESSID,跟客戶端的PHPSESSID值是一樣的。
那麼問題來了,上面說的兩件事,是在程式執行到session_start(),就完成的嗎?這兩件事,誰先誰後呢?
程序2:
session_start();
$_SESSION['uname'] = 'monkey';
$_SESSION['ukey'] = 201199999;
sleep(30);
?>
先把客戶端和服務端的session資料通通刪除,然後執行程式2,趁著程式裡的sleep30秒的工夫,去查看客戶端和服務端的session狀況,發現:在程式執行過程中,客戶端並沒有建立保存PHPSESSID的cookie文件,服務端卻已經有了保存session內容的臨時文件,但是文件裡沒有內容,等30秒時間過了之後,客戶端的cookie文件才會生成,服務端的session檔案裡才有了內容。
由此推斷大致流程應該為:在程式執行到session_start()的時候,服務端先產生PHPSESSID,並產生相對應的session文件,但是在程式進行$_SESSION賦值的時候,並沒有把對應的值寫入到session文件裡,姑且臆斷為保存在內存裡吧,到了程序執行完畢後,才會在客戶端生成保存PHPSESSID的cookie文件,並把$_SESSION變量裡的值寫入服務端的session文件裡,至於最後兩個步驟誰先誰後,暫時還沒想到好方法來證明。
為了更進一步論證,刪除客戶端和服務端的session相關內容執行程序3,觀察第一次和第二次的結果:
程序3:
session_start();
$_SESSION[' uname'] = 'monkey';
$session_id = session_id();
$sess_file = "/tmp/sess_".$session_id;
$content = file_get_contents($sess_file);
_COOKIE['PHPSESSID'] .'***';
echo '
' . $_SESSION['uname'] . '
';
echo '***'.$content.'* **';
?>
上面說的是第一次sessin_start()的執行方式,也就是一套程式裡,第一個session_start()出現的時候所做的事情,下面來看之後的session_start():
假設的php.ini配置:session.cookie_lifetime = 0
程式4:
session_start()); ];
?>
現在,客戶端已經有了保存PHPSESSID的cookie文件,服務端也有了保存session內容的sess_文件,執行程式4,會列印出正常的內容。這時,如果強行關閉瀏覽器,再執行程式4,結果會怎麼樣呢?
session_start ()首先會去取得客戶端cookie裡的PHPSESSID,然後與「sess_」組成文件名,去服務端查找這個文件,然後取出文件裡的內容,把內容放到$_SESSION全域變數里以供使用。瀏覽器強行關閉,再打開,之前的PHPSESSID遺失,這時遇到session_start()就相當於上面說的第一次執行,會產生一個新的PHPSESSID,這個PHPSESSID匹配不到之前那個服務端的sess_文件,所以取不到內容。當然,服務端也有能跟這個PHPSESSID相符的文件,不過,那個文件還是空的。
所以,有的系統為了實現同一用戶只能在一台機器甚至一個瀏覽器登入的機制,如果沒有修改session.cookie_lifetime的設置,就會出現強行關閉瀏覽器之後,在服務端session生存期截止前該,使用者登入不進去的情況,比較好的方法是把session.cookie_lifetime設定成一個比較大的值,反正一個cookie檔案存在時間久一些也沒什麼影響。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。
