一、Session和Cookie的區別
Session是在服務器端保持會話數據的一種方法(通常用于pc端網站保持登錄狀態,手機端通常會使用token方式實現),存儲在服務端。
Cookie是在客戶端保持用戶數據,存儲位置是客戶端(瀏覽器或者手機端)。
?
二、原理
1、當代碼session_start(); 運行的時候,就在服務器上產生了一個session文件,隨之也產生了與之唯一對應的一個session_id。
2、定義的Session變量以一定形式存儲在剛才產生的session文件中。客戶端將session_id傳遞給服務端,服務端根據session_id找到對應的文件,讀取的時候,對文件內容進行反序列化就能得到session的值,保存的時候先序列化再寫入。由此通過session_id可以取出之前定義的變量。
3、也就是說,Session_id是取得存儲在服務器端Session變量的身份證。
注:PHP中的Session在默認的情況下,是使用客戶端的Cookie來保存session_id的(session_start();之后,會自動將session_id存儲在cookie中),但是必須注意,Session不一定必須依賴Cookie,這也就是Session相比于Cookie的高明之處。當客戶端的Cookie被禁用或出現問題時,PHP會自動把session_id附著在URL中,這樣再通過session_id就能實現跨頁使用session變量了。但是這種附著也是有一定條件的,即php.ini文件中的“session.use_trans_sid=1”或者編譯時打開了--enable-trans-sid選項。
?
三、實驗cookie禁用后,session的傳遞
1、cookie未禁用時的結果
(1)php文件
c.php
<?php
session_start();
$_SESSION['name'] = "xiaobudiu";
echo $_SESSION['name'];
echo "<hr>";
var_dump($_COOKIE);
echo "<hr>";
$url = "<a href = 'b.php'>下一頁</a>";
echo $url;
?>
b.php
<?php
session_start();
echo $_SESSION['name'];
echo "<hr>";
var_dump($_COOKIE);
die;
?>
(2)此時,運行c.php代碼在瀏覽器會得到類似下面結果:
(3)此時點擊“下一頁”,跳轉到b.php
2、禁用掉cookie之后,重新運行代碼
注:禁用cookie位置:chrome://settings/content
得到的結果:
也就是說,在不更改php.ini配置文件的前提下,禁用掉cookie之后,默認session是無法跨頁傳輸的
?
?
3、解決禁用掉cookie之后,讓session仍然可以正常傳輸
(1)關閉php.ini配置文件中?session.use_only_cookies,打開php.ini配置文件中session.use_trans_sid,如下:
session.use_trans_sid = 1
session.use_only_cookies = 0
(2)重新運次c.php
點擊下一頁進入b.php
可以看到,在瀏覽器禁用cookie之后,session仍然是可以繼續傳輸的,只不過需要進行配置而已。
但事實上,并不太建議,也不需要這么做。畢竟是存在安全風險的。而且目前瀏覽器基本也不會主動禁用cookie。
?
四、Session在大型網站應用中需要注意的問題
?
1、如何解決Session文件過多,消耗IO性能
建議:可以更改php.ini的 session.save_handler 參數為redis或memcache等內存緩存數據庫。
?
2、解決Session的同步問題
我們前端可能有很多臺服務器,用戶在A服務器上登錄了,種下了session信息,然后訪問網站的某些頁面沒準跳到B服務器上去了,如果這個時候B服務器上沒有session信息又沒有做特殊處理,可能就會出問題了。
解決方案:
(1)更改php.ini的 session.save_handler 參數為redis或memcache等內存緩存數據庫
(2)還有一種方式是通過加密的cookie來實現,用戶在A服務器上登錄成功,在用戶的瀏覽器上種上一個加密的cookie,當用戶訪問B服務器時,檢查有無 session,如果有當然沒問題,如果沒有,就去檢驗cookie是否有效,cookie有效的話就在B服務器上重建session。這種方法其實很有 用,如果網站有很多個子頻道,服務器也不在一個機房,session沒辦法同步又想做統一登錄那就太有用了。
(3)當然還有一種方法就是在負載均衡那一層保持會話,把訪問者綁定在某個服務器上,他的所有訪問都在那個服務器上就不需要session同步了(比如負載均衡中的ip_hash)。
?