天天看點

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

1. session概念

2. http協定與狀态保持

3. 了解cookie

4. php中session的生成機制

5. php中session的過期回收機制

6. php中session的用戶端存儲機制

1. session概念

在web伺服器蓬勃發展的時代,session在web開發語境下的語義是指一類用來在用戶端與伺服器之間保持狀态的解決方案。

2. http協定與狀态保持

http協定本身是無狀态的,用戶端隻需要簡單的向伺服器請求下載下傳某些檔案,無論是用戶端還是伺服器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的。

然而人們很快發現如果能夠提供一些按需生成的動态資訊會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐漸添加了表單、腳本、DOM等用戶端行為,另一方面在伺服器端則出現了CGI規範以響應用戶端的動态請求,作為傳輸載體的HTTP協定也添加了檔案上載、cookie這些特性。其中cookie的作用就是為了解決HTTP協定無狀态的缺陷所作出的努力。至于後來出現的session機制則是又一種在用戶端與伺服器之間保持狀态的解決方案。

session機制可能需要借助于cookie機制來達到儲存辨別的目的。是以有必要了解下cookie。

3. 了解cookie

cookie分發是通過擴充HTTP協定來實作的,伺服器通過在HTTP的響應頭中加上一行特殊的訓示以提示浏覽器按照訓示生成相應的cookie。然而純粹的用戶端腳本如JavaScript或者VBScript也可以生成cookie。

而cookie 的使用是由浏覽器按照一定的原則在背景自動發送給伺服器的。浏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用範圍大于等于将要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給伺服器。

cookie的内容主要包括:名字,值,過期時間,路徑和域。

其中域可以指定某一個域比如.google.com,相當于總店招牌,比如寶潔公司,也可以指定一個域下的具體某台機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。路徑就是跟在域名後面的URL路徑,比如/或者/foo等等,可以用某飄柔專櫃做比。

路徑與域合在一起就構成了cookie的作用範圍。

如果不設定過期時間,則表示這個cookie的生命期為浏覽器會話期間,隻要關閉浏覽器視窗,cookie就消失了。這種生命期為浏覽器會話期的 cookie被稱為會話cookie。會話cookie一般不存儲在硬碟上而是儲存在記憶體裡,當然這種行為并不是規範規定的。如果設定了過期時間,浏覽器就會把cookie儲存到硬碟上,關閉後再次打開浏覽器,這些cookie仍然有效直到超過設定的過期時間

存儲在硬碟上的cookie 不可以在不同的浏覽器間共享,可以在同一浏覽器的不同程序間共享,比如兩個IE視窗。

這是因為每中浏覽器存儲cookie的位置不一樣,比如

Chrome下的cookie放在:

C:\Users\sharexie\AppData\Local\Google\Chrome\User Data\Default\Cache

Firefox下的cookie放在:

C:\Users\sharexie\AppData\Roaming\Mozilla\Firefox\Profiles\tq2hit6m.default\cookies.sqlite (倒數第二個檔案名是随機的檔案名字)

Ie下的cookie放在:

C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Cookies

(網上都說是在這裡,但是我一直沒找到)

我在這裡也有一個測試,在firefox下用httplook軟體進行嗅探:

1、在本機上第一次打開必應網站,抓包:

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

傳回的資料如下:

HTTP/1.1 200 OK

Cache-Control: private, max-age=0

Content-Type: text/html; charset=utf-8

Content-Encoding: gzip

Set-Cookie: _FS=NU=1; domain=.bing.com; path=/

Set-Cookie: _SS=SID=442E36ABF8F5431E8DFF0CAC018437E3; domain=.bing.com; path=/

Set-Cookie: MUID=32B1FE9DB0EB65B52006FD50B1E86565; expires=Sun, 31-Aug-2014 11:35:51 GMT; domain=.bing.com; path=/

Set-Cookie: OrigMUID=32B1FE9DB0EB65B52006FD50B1E86565%2c15deb35b84a74788ae2d9978e3e657b1; expires=Sun, 31-Aug-2014 11:35:51 GMT; domain=.bing.com; path=/

Set-Cookie: SRCHD=D=2454455&MS=2454455&AF=NOFORM; expires=Sun, 31-Aug-2014 11:35:51 GMT; domain=.bing.com; path=/

Set-Cookie: SRCHUID=V=2&GUID=F6DCC04B2CC54139928925763DAEE04A; expires=Sun, 31-Aug-2014 11:35:51 GMT; path=/

Set-Cookie: SRCHUSR=AUTOREDIR=0&GEOVAR=&DOB=20120831; expires=Sun, 31-Aug-2014 11:35:51 GMT; domain=.bing.com; path=/

P3P: CP=”NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND”

Date: Fri, 31 Aug 2012 11:35:50 GMT

Content-Length: 12787

X-Cache-Lookup: MISS from proxy:8080

我們可以看到sessionId為442E36ABF8F5431E8DFF0CAC018437E3,domain為.bing.com; path為/。伺服器為本使用者建立一個session,id為442E36ABF8F5431E8DFF0CAC018437E3作為客服端的cookie中的SID的值。

2、第二次請求必應網站,請求内容如下:

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

看到請求中帶有sid為442E36ABF8F5431E8DFF0CAC018437E3的cookie。

伺服器傳回資料:

HTTP/1.1 200 OK

Cache-Control: private, max-age=0

Content-Type: text/html; charset=utf-8

Content-Encoding: gzip

P3P: CP=”NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND”

Date: Fri, 31 Aug 2012 11:41:12 GMT

Content-Length: 12437

X-Cache-Lookup: MISS from proxy:8080

伺服器檢視本tmp目錄中有一個檔案的名字和SID比對,知道是一個老使用者,沒有建立session,直接傳回資料。

當然也有很多304的傳回,表示在expires内直接用使用者的緩存即可。

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

4. php中session的生成機制

我們先來分析一下PHP中是怎麼生成一個session的。設計出session的目的是保持每一個使用者的各種狀态來彌補HTTP協定的不足(無狀态)。session是儲存在伺服器的,既然它用于保持每一個使用者的狀态那它利用什麼來差別使用者的呢?這個時候就得借助cookie了。當我們在代碼中調用session_start();時,PHP會同時往SESSION的存放目錄(預設為/tmp/)和用戶端的cookie目錄各生成一個檔案。session檔案名稱像這樣:

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

格式為sess_{SESSIONID} ,這時session檔案中沒有任何内容,當我們在session_start();添加了這兩行代碼:

$_SESSION['name'] =’sharexie’;

$_SESSION['webUlr'] = ’www.qq.com’;

這時檔案就有内容了:

name|s:8:”sharexie”;webUlr|s:10:”www.qq.com”;

這時再看看cookie:

深入了解session機制 1. session概念 2. http協定與狀态保持 3. 了解cookie 4. php中session的生成機制 5. php中session的過期回收機制 6. php中session的用戶端存儲機制

可以看到伺服器為我們自動生成了一個cookie,cookie名稱為”PHPSESSID”,cookie内容是一串字元,其實這串字元就是{SESSIONID}。當我們使用session時,PHP就先生成一個唯一的SESSIONID号(如2bd170b3f86523f1b1b60b55ffde0f66),再在我們伺服器的預設目錄下生成一個檔案,檔案名為sess_{SESSIONID},同時在目前使用者的用戶端生成一個cookie,内容已經說過了。這樣PHP會為每一個使用者生成一個SESSIONID,也就是說一個使用者一個session檔案。PHP第一次為某個使用者使用session時就向用戶端寫入了cookie,當這個使用者以後通路時,浏覽器會帶上這個cookie,PHP在拿到cookie後就讀出裡面的SESSIONID,拿着這個SESSIONID去session目錄下找session檔案。

5. php中session的過期回收機制

我們明白了session的生成及工作原理,發現在session目錄下會有許多session檔案。當然這些檔案一定不是永遠存在的,PHP一定提供了一種過期回收機制。在php.ini中session.gc_maxlifetime為session設定了生存時間(預設為1440s)。如果session檔案的最後更新時間到現在超過了生存時間,這個session檔案就被認為是過期的了。在下一次session回收的時候就會被删除。那下一次session回收是在什麼時候呢?這和php請求次數有關的。在PHP内部機制中,當php被請求了N次後就會有一次觸發回收機制。到底是請求多少次觸發一次是通過以下兩個參數控制的:

session.gc_probability = 1

session.gc_divisor = 100

這是php.ini的預設設定,意思是每100次PHP請求就有一次回收發生。機率是gc_probability/gc_divisor (這裡我把session.gc_divisor改為1,好像通路了很多次都沒有觸發回收事件,不知道什麼原因)。我們了解了伺服器端的session過期機制,再來看看用戶端的cookie的過期機制。

如果cookie失效了浏覽器自然發送不了cookie到伺服器,這時即使伺服器的session檔案存在也沒用,因為PHP不知道要讀取哪個session檔案。我們知道PHP的cookie過期時間是在建立時設定的,那麼PHP在建立session的同時為用戶端建立的cookie的生命周期是多久呢?這個在php.ini中有設定:session.cookie_lifetime 。這個值預設是0,代表浏覽器一關閉SESSIONID就失效。那就是說我們把session.gc_maxlifetime和session.cookie_lifetime設定成同一個值就可以控制session的失效時間了。

6. php中session的用戶端存儲機制

由于cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回伺服器。解決辦法有:

1、URL重寫,就是把session id直接附加在URL路徑的後面,一種是作為URL路徑的附加資訊,表現形式為http://…../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

2、另一種是作為查詢字元串附加在URL後面,表現形式為http://…../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

這兩種方式對于使用者來說是沒有差別的,隻是伺服器在解析的時候處理的方式不同,采用第一種方式也有利于把session id的資訊和正常程式參數區分開來。

為了在整個互動過程中始終保持狀态,就必須在每個用戶端可能請求的路徑後面都包含這個session id。

3、表單隐藏字段。就是伺服器會自動修改表單,添加一個隐藏字段,以便在表單送出時能夠把session id傳遞回伺服器。比如下面的表單

<form name=”testform” action=”/xxx”>

<input type=”text”>

</form>

在被傳遞給用戶端之前将被改寫成

<form name=”testform” action=”/xxx”>

<input type=”hidden” name=”jsessionid” value=”ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764″>

<input type=”text”>

</form>

實際上這種技術可以簡單的用對action應用URL重寫來代替。

php