Session過期后數據會丟失,因為默認存儲在服務器上并由垃圾回收機制清理;防止session劫持需使用https、設置Cookie屬性、定期更換session id、驗證用戶信息、縮短過期時間及使用Token;跨域共享session可通過設置cookie域、jsonp、cors、postmessage或sso實現;session數據默認存于服務器文件中,也可存入數據庫或緩存系統如redis;銷毀session需依次執行session_unset()、刪除cookie及session_destroy()以確保徹底清除。
php保存Session值,簡單來說,就是利用$_SESSION這個全局變量,把你想存的數據放進去。但Session的背后,其實涉及到服務器和客戶端之間如何維持狀態,以及一些安全和性能上的考量。
PHP Session操作,可以理解為一系列對$_SESSION數組的操作,以及一些配置選項的調整。
Session過期后,存儲的數據會丟失嗎?
是的,Session過期后,存儲的數據會丟失。Session的數據默認是存儲在服務器上的,當Session過期或者被銷毀時,服務器會清除這些數據??蛻舳酥皇潜4嬉粋€Session ID,用來告訴服務器“我是誰”。
立即學習“PHP免費學習筆記(深入)”;
具體來說,Session的過期時間由session.gc_maxlifetime配置項決定,單位是秒。當Session長時間沒有活動時,服務器的垃圾回收機制(garbage Collection)可能會清理掉這些Session數據。
還有一種情況是,如果用戶手動關閉了瀏覽器,或者清除了瀏覽器的Cookie,那么Session ID也會丟失,導致服務器無法找到對應的Session數據,相當于Session失效了。
所以,如果需要長期保存數據,不要依賴Session。可以考慮使用數據庫、文件或者Cookie等方式來存儲。
如何防止Session劫持?
Session劫持是指攻擊者通過某種方式獲取了用戶的Session ID,然后冒充用戶進行非法操作。防止Session劫持,可以從以下幾個方面入手:
-
使用https: HTTPS可以加密客戶端和服務器之間的通信,防止Session ID在傳輸過程中被竊取。這是最基本也是最重要的一點。
-
設置session.cookie_httponly = true: 這個配置項可以防止客戶端腳本(如JavaScript)訪問Session Cookie,從而降低xss攻擊的風險。
-
設置session.cookie_secure = true: 這個配置項可以確保Session Cookie只在HTTPS連接下傳輸。
-
定期更換Session ID: 可以使用session_regenerate_id()函數來定期更換Session ID,即使攻擊者獲取了之前的Session ID,也會失效。注意,更換Session ID后,原來的Session數據仍然有效。
-
驗證用戶代理(User Agent)和IP地址: 可以在Session中存儲用戶的User Agent和IP地址,并在每次請求時進行驗證。如果User Agent或IP地址發生變化,可以認為Session可能被劫持,并銷毀Session。但是,這種方法可能會導致誤判,因為用戶的IP地址可能會因為網絡環境的變化而改變。
-
設置合理的Session過期時間: 縮短Session的過期時間,可以降低Session被劫持的風險。
-
使用Session Token: 每次生成頁面時,生成一個隨機的Token,并將這個Token存儲在Session中。同時,將這個Token嵌入到頁面中的表單或者鏈接中。在處理表單提交或者鏈接點擊時,驗證Token是否匹配。這樣可以防止csrf攻擊,也能在一定程度上防止Session劫持。
如何跨域共享Session?
跨域共享Session是一個比較復雜的問題,涉及到瀏覽器的同源策略。簡單來說,如果兩個網站的域名、協議或者端口號不同,就被認為是跨域的。默認情況下,瀏覽器不允許跨域訪問Cookie,因此Session也無法跨域共享。
以下是一些常用的跨域共享Session的方法:
-
設置session.cookie_domain: 可以將session.cookie_domain設置為頂級域名,例如.example.com。這樣,所有子域名下的網站都可以訪問這個Session Cookie。但是,這種方法只適用于父子域名之間。
-
使用JSONP: JSONP是一種利用<script>標簽的跨域請求方式。可以將Session ID作為參數傳遞給另一個域名的服務器,然后服務器返回一段JavaScript代碼,將Session ID設置到另一個域名的Cookie中。但是,JSONP只支持GET請求,而且存在安全風險。</script>
-
使用CORS: CORS(Cross-Origin Resource Sharing)是一種W3C標準,允許服務器設置HTTP頭部,告訴瀏覽器允許哪些域名進行跨域訪問。需要在服務器端設置Access-Control-Allow-Origin頭部,指定允許跨域訪問的域名。
-
使用PostMessage: PostMessage是一種html5 API,允許不同域名下的網頁之間進行通信??梢詫ession ID通過PostMessage發送給另一個域名的網頁,然后另一個域名的網頁將Session ID設置到Cookie中。
-
使用統一認證中心(SSO): SSO是一種集中管理用戶身份驗證的解決方案。用戶只需要在一個網站登錄一次,就可以訪問所有集成了SSO的網站。SSO通常使用OAuth或者SAML等協議來實現。
選擇哪種方法,取決于具體的應用場景和安全需求。
Session數據存儲在哪里?
Session數據默認存儲在服務器上的文件中。具體存儲位置由session.save_path配置項決定。默認情況下,存儲在/tmp目錄下。
也可以將Session數據存儲在數據庫中。需要實現SessionHandlerInterface接口,并使用session_set_save_handler()函數來注冊自定義的Session處理函數。
將Session數據存儲在數據庫中,可以方便地進行Session數據的管理和備份,也更容易實現Session的持久化。
還可以將Session數據存儲在redis或者memcached等緩存系統中。這種方式可以提高Session的讀寫性能。
如何銷毀Session?
銷毀Session,可以使用以下步驟:
-
session_unset(): 清空$_SESSION數組中的所有值。
-
session_destroy(): 銷毀Session。這個函數會刪除服務器上的Session數據。
-
刪除Session Cookie: 為了確??蛻舳艘睬宄薙ession ID,需要刪除Session Cookie??梢允褂胹etcookie()函數來刪除Cookie,將Cookie的過期時間設置為過去的時間。
以下是一個完整的銷毀Session的示例代碼:
<?php session_start(); // 清空$_SESSION數組 session_unset(); // 刪除Session Cookie if (ini_get("session.use_cookies")) { $params = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] ); } // 銷毀Session session_destroy(); ?>
注意,session_destroy()函數只是銷毀服務器上的Session數據,并不會立即刪除Session Cookie。需要手動刪除Session Cookie,才能確??蛻舳艘睬宄薙ession ID。