瀏覽器透過web訪問伺服器,伺服器的web服務開啟後,第一步就是開啟session,這也是session的第一階段:
session_start()
這個函式的作用:開啟session,然後根據以前設定的session_name去讀取cookie資訊,判斷$_Cookies[$session_name]判斷是否有值,也就是是否存在session_id,如果存在就用這個session_id,如果沒有就會隨機生成一個唯一的32位的數值,將這個數值賦值給session_id。這個session_id就代表當前訪問的使用者。然後初始化$SESSION這個變數,根據session_id讀取session檔案中的內容(如果有session_id所對應的儲存檔案的話),把內容反序列化之後賦值到$SESSION這個變數中,這個階段還有一個特別關鍵的作用,還會判斷那些session檔案已經過期,呼叫gc程序,刪除掉過期的session檔案。gc如何判斷檔案是否過期,如何操作後面再說
session_start(); echo "SID: ".SID.""; echo "session_id(): ".session_id().""; echo "COOKIE: ".$_COOKIE["PHPSESSID"];
輸出:
SID:PHPSESSID=bjjwfoo45hajsjv89trsgtiertbuiwom
session_id():bjjwfoo45hajsjv89trsgtiertbuiwom
cookie:提示Notice:undefined index:PHPSESSID
這個因為瀏覽器第一次請求還沒有在cookie中儲存session_id,這個cookie的一個特性,只有當第一次請求之後,伺服器接收到請求才在伺服器端設定cookie,儲存session_id。
注意:cookie中儲存的session_id預設是會話時間
SID:是系統常量,SID包含著會話名以及會話ID的常量,格式為“name=ID”,如果cookie中已經存在session_id,SID就為一個空字串,不然就是"name=ID"
第二階段就是指令碼執行期間:
php只是對$_SESSION這個變數進行增刪改查的操作,需要注意:這個階段並沒有影響到session檔案裡面的內容,除非你在這個階段session_destroy()了,除此之外,該階段不會對session檔案有任何影響
第三階段:指令碼執行結束
在這個階段才會對session檔案進行操作,也就是這個階段才會把$_SESSION陣列中的資料序列化然後儲存到session檔案。
session的儲存方式
預設會儲存在伺服器的臨時目錄,以檔案的形式儲存,檔名為(sess_+session_id),這些都可以在php.ini檔案中配置,檔案內容為序列化的資料,如下:
$_SESSION['name'] = ‘張三' $_SESSION['age'] = 18
session檔案為:
name|i:張三;age|i:18
下面是常用的php.ini檔案中sessionde相關配置:
session.save_handler = files #規定session的儲存方式,預設是檔案,還可以是redis或者是memcache,提升效率 session.save_path = "d:/wamp/tmp" #規定session檔案的儲存目錄 session.use_cookies = 1 #是否使用cookie儲存session_id session.name = PHPSESSID #客戶端儲存session_id的會話名 session.auto_start = 0 #是否自動開啟session session.cookie_lifetime = 0 #設定客戶端中儲存的session_id的過期時間,注意session的過期時間是間隔的,比如20分鐘過期,重新訪問了,session的過期時間會重新計算,cookie的過期時間是累記的 session.serialize_handler = php session.gc_divisor = 1000 session.gc_probability = 1 session.gc_maxlifetime = 1440 #設定session檔案的過期時間
session的垃圾回收機制
一個使用者訪問伺服器會產生一個session檔案,關閉瀏覽器,然後在訪問伺服器又會產生一個新的session檔案,這樣session的垃圾檔案就會很多,長時間不清理就會佔用大量的磁碟空間,訪問session檔案的速度也會降低,gc程序垃圾回收就很有必要了
先提一下PHP的一些清理session的函式
unset($_SESSION['name']) 清理某個變數 session_unset() 不傳引數,清除所有的session變數,但是session檔案還在 session_destroy() 清除session檔案 setcookie(session_name(), '', time()-1000, '/') 設定cookie檔案過期
注意:一般做了session_destroy()操作之後,setcookie(session_name(), '', time()-1000, '/')也是必須的,不然使用者重新重新整理頁面,又會設定一樣的session_id,產生session檔案
然後就是gc自動刪除垃圾檔案:
session.gc_divisor = 1000 session.gc_probability = 1 session.gc_maxlifetime = 1440 #設定session檔案的過期時間
刪除session垃圾檔案的機率是,session.gc_probability/session.gc_divisor=1/1000,也就是說每次session_start()都會有1/1000的機率觸發gc程序,但是1000次中必會有一次,如果session.gc_probalility = 1000,就是100%的機率,也就說每次session_start()都會觸發gc程序
微信小程式中的session應用
微信小程式中並沒有cookie機制,因此除非你在微信小程式中模擬cookie機制的實現,否則你要專門設定程式碼用來傳送session_id。
wx.request({ url: 'https://your_domain.com/api/function', header: { 'content-type': 'application/json', // 預設值 'session_id': wx.getStorageSync('session_id') // 讀取本地快取中的session_id值 }, success: function(res) { console.log(res.data) } })
後端獲取3rd_session的方式也非常簡單,只需要讀取HTTP Header中的3rd_session欄位即可。PHP程式碼示例如下:
session_id($_SERVER["session_id"]); // 將讀取到的前端session_id設定成伺服器端的session_id session_start(); if(isset($_SESSION['session_key'])&&($_SESSION['openid']==$openid)){ // 3rd_session驗證透過 }