深度解剖session運行原理


已經大半年沒有更新博客了,一方面有比博客更重要的事情要做,另外一方面也沒有時間來整理知識,所以希望在接下來的日子里面能夠多多的寫博客來與大家交流

什么是session

 session的官方定義是:Session:在計算機中,尤其是在網絡應用中,稱為“會話控制”。Session 對象存儲特定用戶會話所需的屬性及配置信息。

 說白了session就是一種可以維持服務器端的數據存儲技術。session主要有以下的這些特點:

 

 1. session保存的位置是在服務器端

 2. session一般來說是要配合cookie使用,如果是瀏覽器禁用了cookie功能,也就只能夠使用URL重寫來實現session存儲的功能

 3. 單純的使用session來維持用戶狀態的話,那么當同時登錄的用戶數量較多的時候,或者存在較多的數量的session會導致查詢慢的問題

 本質上:session技術就是一種基於后端有別於數據庫的臨時存儲數據的技術

 

為什么要有session

 主要的一個原因就是HTTP的無狀態性

 因為HTTP的無狀態性,所以我們沒有辦法在HTTP發送請求的時候知道當前用戶的狀態,也就是比如說,當前是哪個用戶的之類的這種信息,所以這個時候我們需要session來標識當前的狀態

 

seesion的工作原理

  接下來,通過一個模擬用戶登錄的流程圖來初步理解session的原理,假設這個時候用戶執行登錄操作,具體的session工作流程如下:

 

整個流程大概分成這樣的幾步:

1. 第一步將本地的cookie中的session標識和用戶名,密碼帶到后台中

2. 第二步后台檢測有沒有對應的session標識,我們以php為例,那么就是檢測有沒有接收到對應的PHPSESSID

3. 沒有的話直接生成一個新的session。有的話,檢測對應的文件是否存在並且有效

3. 失效的話,我們需要清除session然后生成新的session。不失效,使用當前的session

看到這里你可能對session的工作原理有一個初步的理解

session的原理圖如下:

 

session的常見配置

 我們這里以PHP為例來講解一下關於session的配置

 首先我們要在PHP的安裝目錄下面找到php.ini文件,這個文件主要的作用是對PHP進行一些配置,具體以后涉及到再詳講。

  1. 設置session存放在cookie中中標識的字段名,php中默認為PHPSESSID

  對應的設置為:session.name = PHPSESSID

  2. 如果客戶端禁用了cookie,可以通過設置session.use_trans_sid來使標識的交互方式從cookie變為url傳遞

    對應的設置為: session.use_trans_sid = 0

  3. 設置session的保存位置

  對應的設置是session.save_path="D:\phpStudy\PHPTutorial\tmp\tmp"

 

PHP中session實戰

 首先我們需要安裝wamp或者是phpstudy,具體方式自行百度

 為了方便觀察session文件的變化,我們需要找到session的保存路徑(在php.ini中找到session.save_path),如下:

 

 然后找到所指向的目錄,注意一般來說session是使用files的形式來保存的,但是我們也可以根據自己的實際情況進行修改。我們可以在php.ini文件中進行修改和查看。

 

 使用session的第一步,我們要打開session,使用session_start(),然后我們給創建的session添加一個變量,我們假設為demo1,值為default ,代碼如下:

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/12/16
 */
session_start();// 打開session
$_SESSION["demo1"] = "default";
?>

 

執行效果如下:

 打開對應的文件,里面的內容如下:

 s:7 表示的是類型為string類型,長度為7個長度的字符串

 如果我們對session中的內容進行重新編輯的話,效果如下:

 我們觀察最近一條的修改日期,我們可以發現就是日期發生了變化,但是文件名沒有變化,也就是說,修改session中的內容不會導致文件被新建,而是執行對文件的重新寫入操作

 session的銷毀

 銷毀session一般有兩種方式,unset和session_destroy,我們先來說說第一種

 代碼如下:

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/12/16
 */
session_start();// 打開session
$_SESSION["demo1"] = "default_1";
//session的銷毀
unset($_SESSION);
?>

 

這一個相當於沒有刪除session文件,但是使得即使有對應的PHPSESSID也無法獲取到相應的session

session_destroy()相對來說比較徹底,直接刪除對應的session文件

 

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/12/16
 */
session_start();// 打開session
$_SESSION["demo1"] = "default_1";
var_dump(session_name());
//session的銷毀
session_destroy();
?>

 

 

 

運行的效果如下:

對於個人來說比較推薦使用第二種方法,因為當要銷毀session的時候,那么也就意味着session已經失效了,所以這個時候我們把它給刪掉才是最好的處理方式,一方面可以減少對硬盤的存儲,另外一方面可以相對優化session的查詢速度。

 好了,這個時候我們應該要設置傳遞給瀏覽器端的cookie了,默認是自動傳送,但是我們應該要學習的是怎樣通過后端設置cookie過去

其中有兩個方法與session有關的方法我們需要記住,第一個是session_name(),這個是獲取cookie的key值得,第二個是session_id,這個是session的文件名

設置的示例代碼:

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/12/16
 */
session_start();// 打開session
$_SESSION["demo1"] = "default_1";
setCookie(session_name(),session_id(),time()-1000);
?>

 

在設置cookie的時候,我們為了程序的安全性,我們應該要禁止JS可以對cookie進行重寫,所以需要設置HTTP ONLY,具體的設置方法在Php.ini中找到session.cookie_httponly

然后將其的值設置為1或者true即可

除此之外還可以通過setCookie和ini_set()來動態設置HTTPONLY屬性

在使用session的時候,雖然會從瀏覽器把PHPSESSID傳給后端,但是這個課程不需要人為的去參與。我們只需要保證HTTPONLY被設置就行了。下面是完整的代碼:

 

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/12/16
 */
session_start();// 打開session
if ($_SESSION) {
    var_dump($_SESSION["demo1"]);
} else {
    $_SESSION["demo1"] = "default_" . time();
    var_dump($_SESSION["demo1"]);
    setCookie(session_name(), session_id(), time(), NULL, NULL, NULL, true);
}

?>

 

 

 

 

session的一些相關注意事項

 1. 關閉瀏覽器session同樣存在

 如果我們沒有人為的去設置cookie的生命周期的時候默認關閉瀏覽器session的狀態是無法被保存下來的,因為沒有設置cookie的生命周期,默認這個時候cookie為session cookie也就是在會話存在的時候cookie才有效,所以關閉瀏覽器cookie失效,導致后端拿不到對應的PHPSESSID,所以無法找到對應的session文件

2.  session性能瓶頸怎樣解決?

如果是后端存在大量的session的時候,那么這個時候就會出現性能的瓶頸,例如:當后端同時存在有5000個session文件的時候,假設要找的文件是在第4999個,那么也就是說前面至少需要遍歷4998次,這樣就會浪費過多的時間在后端的循環遍歷查找文件中,所以這個時候最有效的方法是使用redis或者mongodb,原理是通過將原本保存在本地的session文件寫入到內存中,通過內存換空間的形式來達到提升速度

3. 一般不使用URL重寫的方法來傳遞PHPSESSID

其中主要有兩個原因,一個是URL重寫方式傳遞的話會導致URL混亂,影響美觀。另一個是增大了用戶誤操作的幾率

更多的session的相關配置請點擊這里

  

更多的一些PHP.ini中session的含義
[Session]
session.save_handler = files  #session的存儲方式
session.use_cookies= 1  #使用cookies在客戶端保存會話
session.use_only_cookies = 1  #去保護URL中傳送session id的用戶
session.name = PHPSESSID  #session名稱(默認PHPSESSID)
session.auto_start = 0  #不啟用請求自動初始化session
session.cookie_lifetime = 0  #cookie存活時間(0為直至瀏覽器重啟,單位秒)
session.cookie_path = /  #cookie的有效路徑
session.cookie_domain =  #cookie的有效域名
session.cookie_httponly =  #httponly標記增加到cookie上(腳本語言無法抓取)
session.serialize_handler = php  #PHP標准序列化
 
session.gc_probability =1
session.gc_divisor =1000  #建議設置1000-5000
#概率=session.gc_probability/session.gc_divisor(1/1000)
#頁面訪問越頻繁概率越小
session.gc_maxlifetime =1440  #過期時間(默認24分鍾,單位秒)
 
session.bug_compat_42 = off  #全局初始化session變量
session.bug_compat_warn = off
session.referer_check =  #防止帶有ID的外部URL
session.entopy_length = 0  #讀取的字節
session.cache_limiter = {nocache,private,pblic}  #HTTP緩沖類型
session.cache_expire = 180  #文檔過期時間(分鍾)
session.use_trans_sid = 1  #trans_sid支持(默認0)
session.hash_function = 0  #hash方法{0:md5(128 bits),1:SHA-1(160 bits)}
session.hash_bits_per_character = 5  #當轉換二進制hash數據奧可讀形式是,每個字符保留位數
session.save_path =  "/var/lib/php/session"  #session id存放路徑


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM