session 原理

 

Session:在計算機中,尤其是在網絡應用中,稱爲“會話”。

具體到Web中的Session指的就是用戶在瀏覽某個網站時,從進入網站到瀏覽器關閉所經過的這段時間,也就是用戶瀏覽這個網站所花費的時間。因此從上述的定義中我們可以看到,Session實際上是一個特定的時間概念。

一、session是怎麼保存的?怎麼去查看其內容?

session是以文件的形式保存的。php.ini中有個配置項--session.save_path= "";這個裏面填寫的路徑,將會使session文件保存在該路徑下。session文件的命名格式是:"sess_[PHPSESSID的值]"。每一 個文件,裏面保存了一個會話的數據。其實只要使用代碼$_SESSION['user_id'] = $value;就會促發php的session機制,結果往對應的session文件中寫入一個值。

二、session.save_path路徑下這麼多的session文件,php是如何確定要調用哪個session文件的?

php是依據,一個名爲PHPSESSID的cookie,根據它的值,確定要調用哪個session文件的。去瀏覽器中,可以看到一個 cookie名爲PHPSESSID,假如它的值爲"sess_adbjsf2q1ass26oootd163sf84",那麼,當訪問服務器的時候,就 會調用session目錄下名爲"sess_sess_adbjsf2q1ass26oootd163sf84"的文件。其實,PHPSESSID就是一 個會話id,以此來確定,哪個是你的會話數據。

cookie的名字PHPSESSID是可以改的,在php.ini中 session.name = PHPSESSID就是設置該cookie的名字。

結合自己實際開發中遇到的問題,總結一下:要說session跟cookie有關聯的地方,就是跟PHPSESSID這個cookie有綁定關係。 其他,不管你設置什麼cookie,使用session的時候是不會用到這些值的。也無法獲取到。比如同步登陸,設置即使設置了cookie,而你的應用 是依據session判斷是否爲登陸狀態的(事實上也必須如此,因爲session保存在服務器端,安全性更高,哪個依據cookie認爲你已經登陸,那 麼很慘)。

所以,這樣的情況就會出現,即使成功設置了cookie。也還是不能同步登陸。

三、經常遇到的現象:爲什麼刪除一個session文件,之後生成一個session文件,新的文件名字還是與原來一樣?

理解到session文件的命名規則是:“sess_PHPSESSID值“。那麼,就很容易明白了。因爲,客戶端存在 cookie:PHPSESSID。客戶端發送請求後,會將該cookie發送給服務器(php可以使用$_COOKIE['PHPSESSID']看到 其內容),這樣的話,還是會根據PHPSESSID生成一個session文件的。

四、如何查看session文件中的session值?

我在開發中發現,如果僅僅依靠session_start()和$_SESSION['user_id']這樣的代碼,去調試,還不夠全面的瞭解問 題所在。比如,我想知道,session_start()到底在完成哪些操作?如果,想動態,實時知道session的值是如何被改寫的,打開一個 session文件,查看是很瞭然的。原來,裏面就是保存的是一些被序列化後的值。也明白一個知識點,"php聖經"中講解session的時候,提到 session值做被序列化了。下面看到的session內容就是被序列化了。

打開一個session文件,內容如下:

cityID|i:0;cityName|s:3:"all";fanwe_lang|s:5:"zh- cn";fanwe_currency|a:4:{s:2:"id";s:1:"1";s:6:"name_1";s:9:"人民 幣";s:4:"unit";s:3:" ¥";s:5:"radio";s:6:"1.0000";}_fanwe_hash__|s:32:"77c18770c6cb5d89444c407aaa3e8477";

總結出讀取規則:1.每一個session的值是以分號";"分開的。比如“cityID|i:0;cityName|s:3:"all";”就是一個完整的session值結束

2.裏面的讀取規則:符號“|”前面表示session名稱。符號後面是該session的具體信息。包括:數據類型,字符長度,內容。上面第一個就相當於使用如下php代碼訪問:$_SESSION['cityID']

後面的s表示數據類型,這裏s說明是字符串類型。3表示字符長度。最後"all"就表示session的具體值了。就是使用代碼$_SESSION['cityID']後會得到的結果

3.一個session可以保存一個數組。符號{}表示數組的內容。上面的花括號{}是$_SESSION['fanwe_currency']所保存的內容。要想查看id的值,就使用代碼:$_SESSION['fanwe_currency']['id']

五、怎麼樣理解session_start等函數所做的實際操作是什麼?

我是這樣理解的:session_start,可以看成是創建一個session文件。假如有原來的session文件,或許沒有創建。引入一個。往session文件中寫值,那是代碼“$_SESSION['']=” 賦值所完成的操作。
session_start() 生成一個新的session文件名時。會判斷是否存在cookie名爲PHPSESSID的值。如果存在,那麼就會按照它的值,組合成一個文件 名"sess_[phpcookie值]"。所以,在目錄下,老是能夠看到之前刪除過的session文件名。如果將瀏覽器中對應的cookie刪掉。那 麼就不會生成同樣的名字了。如果不存在名爲PHPSESSID的cookie。php所做的估計爲:先發送一個cookie,然後按照cookie的值生 成一個(我可以在瀏覽器中馬上看到一個名爲PHPSESSID的cookie)

其實,現在也更加深刻地理解了一個知識:在調用session_start()之前不能有任何輸出。有輸出就會報錯。

session_start()已經封裝了發送cookie的操作。涉及到http的一個原理:頭部信息必須在內容之前發送才行。所以,使用echo '內容';

header('Content-type: text/xml; charset=gb2312');//頭部信息,不算內容

可以這樣認爲:session_start()內部已經進行了一次發送頭部動作。所以之前不能有任何輸出內容。
手冊中的英文大致是這樣說的:創建一個session,或者恢復當前一個session(基於request請求傳遞的session id)

實際開發應用總結:

只要是同一個用戶的操作。導航程序訪問記錄和團購程序訪問的記錄都是保存在同一個session文件中

如果是不同的域呢?假如用戶訪問cs.test.com和daohang.test.com,兩方程序都設置了session。那麼session的結果

保存在同一個session文件中嗎?

因爲:服務器是統一管理session文件的存放的。而php引擎是根據phpsessionid的值確定要操作哪個session文件。session

文件名的格式是:"sess_[phpcookie值]"。依次尋找對應的session文件(於是在瀏覽器查看名爲PHPSESSIONID的cookie,過

期時間是在會話結束後)
所以,只要cs.test.com和daohang.test.com使用的是同一臺服務器。



這樣的話,假如是多臺服務器的情況。那麼就不得不將session保存在數據庫中去。這樣實現session共享。跟具體的服務器

是無關的。

session文件是某個用戶整個會話過程中數據。那麼,假如cs.test.com和daohang.test.com下的兩個程序運行在同一

個服務器上。就意味着,訪問cs.test.com與訪問daohang.test.com是同一個會話。也就意味着,這兩邊訪問後設置的

session 數據是保存在同一個session文件中的。可以將名爲PHPSESSIONID的cookie,其值看成是一個會話的id。會話結束後,該cookie 過期或者被刪。那麼,服務器對應的session文件(名爲"sess_[phpcookie值]")會被刪掉嗎?查看發現並不會被刪掉。所以纔會有 session文件很多,出現讀取性能的問題。session文件比較多的情況下,產生I/Q讀寫性能問題。瞭解到可以將session文件分多個目錄保 存。php.ini中的配置項session.save_path,前面一個值M可以指定目錄的深度級別。這個沒測試過。需要用到的時候,再去測試一下

待解決疑問

一、session的過期時間是怎麼確定的?
查看session文件內容,發現裏面有個值設置了session文件的過期時間:__HTTP_Session_Expire_TS|i:1297750868;

已掌握的信息:
PHPSESSID該cookie的過期時間在瀏覽器中顯示:會話結束後過期

所有的session文件沒有被自動刪掉,只是有個過期時間,以此決定:是新生成一個session文件還是使用原來的。

原來:服務器定期session清理機制估計會用到這個東西

二、如果沒有設置php.ini中的參數。php默認會將session文件保存到什麼位置?

附網文:php.ini中配置session參數的說明。

【Session】

 

[服務端]

session.save_handler = files

默認爲file,定義session在服務端的保存方式,file意爲把sesion保存到一個臨時文件裏,如果我們想自定義別的方式保存

(比如用數據庫),則需要把該項設置爲user;

 

session.save_path = "D:/APMServ5.2.0/PHP/sessiondata/"

定義服務端存儲session的臨時文件的位置。

 

session.auto_start = 0

如置1,則不用在每個文件裏寫session_start(); session自動start :)

 

session.gc_probability = 1

session.gc_divisor    = 100

session.gc_maxlifetime = 1440

這三個配置組合構建服務端session的垃圾回收機制

session.gc_probability 與session.gc_divisor構成執行session清理的概率,理論上的解釋爲服務端定期有一定的概率調用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 = 

這個設置在session.use_trans_sid = 1的時候纔會生效,目的是檢查HTTP頭中的"Referer"以判斷包含於URL中的會話id是否

有效,HTTP_REFERER必須包含這個參數指定的字符串,否則URL中的會話id將被視爲無效。所以一般默認爲空,即不檢查。 

 

session.name = PHPSESSID

定義sessionid的名稱,即變量名,所以通過瀏覽器http工具看到的http頭文件裏的PHPSESSID=##############;

 

session.hash_function = 0

選擇session_name的加密方式,0代表md5加密,1代表sha1加密,默認是0,但是據說用sha1方式加密,安全性更高;

 

session.hash_bits_per_character = 4

指定在session_name字符串中的每個字符內保存多少位二進制數,這些二進制數是hash函數的運算結果。

4   bits:   0-9,   a-f 

5   bits:   0-9,   a-v 

6   bits:   0-9,   a-z,   A-Z,   "-",   ","

 

url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset="

指定重寫哪些HTML標籤來包含sid(session_id)(僅在"session.use_trans_sid"打開的情況下有效),URL重寫器將添加一個

隱藏的"<input>",它包含了本應當額外追加到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就要廢除這個設置,直

接定義爲關閉,所以沒必要研究這兩個了;

發佈了14 篇原創文章 · 獲贊 14 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章