原文:
PHP函數(shù)參考22-session擴(kuò)展 - 9ong
PHP函數(shù)參考23-正則相關(guān)函數(shù) - 9ong
工作流程
會話的工作流程很簡單。當(dāng)開始一個會話時,PHP 會嘗試從請求中查找會話 ID (通常通過會話 cookie),如果請求中不包含會話 ID 信息,PHP 就會創(chuàng)建一個新的會話。會話開始之后,PHP 就會將會話中的數(shù)據(jù)設(shè)置到 $_SESSION 變量中。當(dāng) PHP 停止的時候,它會自動讀取 $_SESSION中的內(nèi)容,并將其進(jìn)行序列化,然后發(fā)送給會話保存管理器來進(jìn)行保存。
默認(rèn)情況下,PHP 使用內(nèi)置的文件會話保存管理器(files)來完成會話的保存。也可以通過配置項(xiàng) session.save_handler 來修改所要采用的會話保存管理器。對于文件會話保存管理器,會將會話數(shù)據(jù)保存到配置項(xiàng) session.save_path 所指定的位置。
可以通過調(diào)用函數(shù) session_start() 來手動開始一個會話。如果配置項(xiàng) session.auto_start 設(shè)置為1,那么請求開始的時候,會話會自動開始。
PHP 腳本執(zhí)行完畢之后,會話會自動關(guān)閉。同時,也可以通過調(diào)用函數(shù) session_write_close() 來手動關(guān)閉會話。
會話id
一個訪問者訪問你的 web 網(wǎng)站將被分配一個唯一的 id, 就是所謂的會話 id. 這個 id 可以存儲在用戶端的一個 cookie 中,也可以通過 URL 進(jìn)行傳遞。
有兩種方式用來傳送會話 ID:
- Cookies
- URL 參數(shù)
會話模塊支持這兩種方式。 Cookie 方式相對好一些,但是用戶可能在瀏覽器中關(guān)閉 Cookie,所以第二種方案就是把會話 ID 直接并入到 URL 中,以保證會話 ID 的傳送。
無需開發(fā)人員干預(yù),PHP 就可以自動處理 URL 傳送會話 ID 的場景。如果啟用了 session.use_trans_sid 選項(xiàng), PHP 將會自動在相對 URI 中包含會話 ID。
會話開始之后,可以使用 SID 常量。如果客戶端未提供會話 cookie,該常量的展開形式為 session_name=session_id,反之,該常量為空字符串。因此,可以直接在 URL 中包含此常量的展開字符串而無需考慮會話 ID 的實(shí)際傳送方式。
序列化
$_SESSION (和所有已注冊得變量) 將被 PHP 使用內(nèi)置的序列化方法在請求完成時進(jìn)行序列化。
會話安全
安全重于業(yè)務(wù),目前大部分場景都還是采用php的會話方式實(shí)現(xiàn)通信定制,對于安全,要重視再重視,先從會話安全開始,了解會話管理、會話問題、會話安全配置等:
-
會話信息不安全,會話ID泄露。
會話模塊無法保證你存儲在會話中的信息只能被創(chuàng)建會話的用戶本人可見。你需要采取額外的手段來保護(hù)會話中的機(jī)密信息,至于采取何種方式來保護(hù)機(jī)密信息,取決于你在會話中存儲的數(shù)據(jù)的機(jī)密程度。
有很多種方式都可以導(dǎo)致會話 ID 被泄露給第三方。例如,JavaScript 注入,URL 中包含會話 ID,數(shù)據(jù)包偵聽,或者直接訪問你的物理設(shè)備等。如果會話 ID 被泄漏給第三方,那么他們就可以訪問這個會話 ID 可以訪問的全部資源。
-
嚴(yán)格會話
從 PHP 5.5.2 開始,新增加了一個配置項(xiàng): session.use_strict_mode。當(dāng)啟用這個配置項(xiàng),并且你所用的會話存儲處理器支持的話,未經(jīng)初始化的會話 ID 會被拒絕,并為其生成一個全新的會話,這可以避免攻擊者使用一個已知的會話 ID 來進(jìn)行攻擊。
-
會話與自動登錄
開發(fā)者不應(yīng)該通過使用長生命周期的會話 ID 來實(shí)現(xiàn)自動登錄功能,因?yàn)檫@種方式提高了會話被竊取的風(fēng)險。開發(fā)者應(yīng)該自己實(shí)現(xiàn)自動登錄的機(jī)制。
-
CSRF跨站請求偽造攻擊
會話和認(rèn)證無法避免跨站請求偽造攻擊。開發(fā)者需要自己來實(shí)現(xiàn)保護(hù)應(yīng)用不受 CSRF 攻擊的功能。
output_add_rewrite_var() 函數(shù)可以用來保護(hù)應(yīng)用免受 CSRF 攻擊。
大部分 Web 應(yīng)用框架都提供了 CSRF 保護(hù)的特性。詳細(xì)信息請參考你所用的 Web 框架的文檔。
從 PHP 7.3 開始,對于會話 cookie 增加了 SameSite 屬性,這個屬性可以有效的降低 CSRF 攻擊的風(fēng)險。
會話文件鎖
無論是通過調(diào)用函數(shù) session_start() 手動開啟會話,還是使用配置項(xiàng) session.auto_start 自動開啟會話,對于基于文件的會話數(shù)據(jù)保存(PHP 的默認(rèn)行為)而言,在會話開始的時候都會給會話數(shù)據(jù)文件加鎖,直到 PHP 腳本執(zhí)行完畢或者顯式調(diào)用 session_write_close() 來保存會話數(shù)據(jù)。在此期間,其他腳本不可以訪問同一個會話數(shù)據(jù)文件。
對于大量使用 Ajax 或者并發(fā)請求的網(wǎng)站而言,這可能是一個嚴(yán)重的問題。解決這個問題最簡單的做法是如果修改了會話中的變量,那么應(yīng)該盡快調(diào)用 session_write_close() 來保存會話數(shù)據(jù)并釋放文件鎖。還有一種選擇就是使用支持并發(fā)操作的會話保存管理器來替代文件會話保存管理器。
自定義會話管理器
如果需要在數(shù)據(jù)庫中或者以其他方式存儲會話數(shù)據(jù),需要使用 session_set_save_handler() 函數(shù)來創(chuàng)建一系列用戶級存儲函數(shù)。 PHP 5.4.0 之后,你可以使用 SessionHandlerInterface 類或者通過繼承 SessionHandler 類來擴(kuò)展內(nèi)置的管理器,從而達(dá)到自定義會話保存機(jī)制的目的。
函數(shù) session_set_save_handler() 的參數(shù)即為在會話生命周期內(nèi)要調(diào)用的一組回調(diào)函數(shù): open, read, write 以及 close。還有一些回調(diào)函數(shù)被用來完成垃圾清理:destroy 用來刪除會話, gc 用來進(jìn)行周期性的垃圾收集。
因此,會話保存管理器對于 PHP 而言是必需的。默認(rèn)情況下會使用內(nèi)置的文件會話保存管理器??梢酝ㄟ^ session_set_save_handler() 函數(shù)來設(shè)置自定義會話保存管理器。一些 PHP 擴(kuò)展也提供了內(nèi)置的會話管理器,例如:sqlite, memcache 以及 memcached,可以通過配置項(xiàng) session.save_handler 來使用它們。
會話管理器工作流程:
會話開始的時候,PHP 會調(diào)用 open 管理器,然后再調(diào)用 read 回調(diào)函數(shù)來讀取內(nèi)容,該回調(diào)函數(shù)返回已經(jīng)經(jīng)過編碼的字符串。然后 PHP 會將這個字符串解碼,并且產(chǎn)生一個數(shù)組對象,然后保存至 $_SESSION 超級全局變量。
當(dāng) PHP 關(guān)閉的時候(或者調(diào)用了 session_write_close() 之后), PHP 會對 $_SESSION 中的數(shù)據(jù)進(jìn)行編碼,然后和會話 ID 一起傳送給 write 回調(diào)函數(shù)。 write 回調(diào)函數(shù)調(diào)用完畢之后,PHP 內(nèi)部將調(diào)用 close 回調(diào)函數(shù)。
銷毀會話時,PHP 會調(diào)用 destroy 回調(diào)函數(shù)。
根據(jù)會話生命周期時間的設(shè)置,PHP 會不時地調(diào)用 gc 回調(diào)函數(shù)。該函數(shù)會從持久化存儲中刪除超時的會話數(shù)據(jù)。超時是指會話最后一次訪問時間距離當(dāng)前時間超過了 $lifetime 所指定的值。
所以,php會話生命周期并不是實(shí)時結(jié)束的,可能過期了,但還能訪問。
Session函數(shù)
-
session_start — 啟動新會話或者重用現(xiàn)有會話
session_start() 會創(chuàng)建新會話或者重用現(xiàn)有會話。如果通過 GET 或者 POST 方式,或者使用 cookie 提交了會話 ID,則會重用現(xiàn)有會話。
-
session_unset — 釋放所有的會話變量
session_unset() 會釋放當(dāng)前會話注冊的所有會話變量。
注意:請不要使用unset(
_SESSION,因?yàn)樗鼘猛ㄟ^全局$_SESSION去注冊會話變量
注意:session_unset僅從會話中刪除變量-會話仍然存在。如果要銷毀會話請使用session_destory
-
session_destroy — 銷毀一個會話中的全部數(shù)據(jù)
session_destroy() 銷毀當(dāng)前會話中的全部數(shù)據(jù),但是不會重置當(dāng)前會話所關(guān)聯(lián)的全局變量,也不會重置會話 cookie。如果需要再次使用會話變量,必須重新調(diào)用 session_start() 函數(shù)。
意味著:session_destory刪除整個會話
注意:刪除當(dāng)前用戶對應(yīng)的session文件以及釋放sessionid,內(nèi)存中的$_SESSION變量內(nèi)容依然保留。
所以徹底的銷毀一個會話,我們建議:
session_start(); $_SESSION["name"] = "tsingchan"; session_unset(); session_destroy(); var_dump($_SESSION); var_dump($_SESSION['name']); //如果沒有session_unset,將會繼續(xù)輸出tsingchan,如果沒有session_detory,那么會話仍然存在,只是name不存在了
-
session_save_path — 讀取/設(shè)置當(dāng)前會話的保存路徑
指定會話數(shù)據(jù)保存的路徑。必須在調(diào)用 session_start() 函數(shù)之前調(diào)用 session_save_path() 函數(shù)。
-
session_name — 讀取/設(shè)置會話名稱
用在 cookie 或者 URL 中的會話名稱,例如:PHPSESSID。只能使用字母和數(shù)字作為會話名稱,建議盡可能的短一些,并且是望文知意的名字(對于啟用了 cookie 警告的用戶來說,方便其判斷是否要允許此 cookie)。如果指定了 name 參數(shù),那么當(dāng)前會話也會使用指定值作為名稱。
請求開始的時候,會話名稱會被重置并且存儲到 session.name 配置項(xiàng)。因此,要想設(shè)置會話名稱,那么對于每個請求,都需要在調(diào)用 session_start() 函數(shù)之前調(diào)用 session_name() 函數(shù)。
-
session_id — 獲取/設(shè)置當(dāng)前會話 ID
如果指定了 id 參數(shù)的值,則使用指定值作為會話 ID。必須在調(diào)用 session_start() 函數(shù)之前調(diào)用 session_id() 函數(shù)。不同的會話管理器對于會話 ID 中可以使用的字符有不同的限制。例如文件會話管理器僅允許會話 ID 中使用以下字符:a-z A-Z 0-9 , (逗號)和 - (減號)
-
session_regenerate_id — 使用新生成的會話 ID 更新現(xiàn)有會話 ID
在不修改當(dāng)前會話中數(shù)據(jù)的前提下使用新的 ID 替換原有會話 ID。
session_regenerate_id([ bool $delete_old_session = FALSE] ) : bool參數(shù)$delete_old_session表示是否刪除原 ID 所關(guān)聯(lián)的會話存儲文件。如果你需要避免會話并發(fā)訪問沖突,那么不應(yīng)該立即刪除會話中的數(shù)據(jù)。如果你需要防止會話劫持攻擊,那么可以立即刪除會話數(shù)據(jù)。
session_start(); $_SESSION["name"] = "tsingchan"; echo session_id(); echo "<br />"; session_regenerate_id(true);//為當(dāng)前會話重新生成會話id,下一次訪問將自動更換會話id(前后端) echo session_id(); echo "<br />"; var_dump($_SESSION); var_dump($_SESSION['name']); //session_unset(); //session_destroy(); -
session_write_close — Write session data and end session
結(jié)束當(dāng)前會話并存儲會話數(shù)據(jù)。
我們可以手動結(jié)束會話。
會話數(shù)據(jù)通常在腳本終止后存儲,而不需要調(diào)用session_write_close(),但是由于會話數(shù)據(jù)被鎖定以防止并發(fā)寫,所以在任何時候只有一個腳本可以對會話進(jìn)行操作。
-
session_set_save_handler — 設(shè)置用戶自定義會話存儲函數(shù)
如果需要在數(shù)據(jù)庫中或者以其他方式存儲會話數(shù)據(jù),需要使用 session_set_save_handler() 函數(shù)來創(chuàng)建一系列用戶級存儲函數(shù)。 PHP 5.4.0 之后,你可以使用 SessionHandlerInterface 類或者通過繼承 SessionHandler 類來擴(kuò)展內(nèi)置的管理器,從而達(dá)到自定義會話保存機(jī)制的目的。
函數(shù) session_set_save_handler() 的參數(shù)即為在會話生命周期內(nèi)要調(diào)用的一組回調(diào)函數(shù): open, read, write 以及 close。還有一些回調(diào)函數(shù)被用來完成垃圾清理:destroy 用來刪除會話, gc 用來進(jìn)行周期性的垃圾收集。
session_set_save_handler有兩種傳參實(shí)現(xiàn)方式:
session_set_save_handler( callable $open, callable $close, callable $read, callable $write, callable $destroy, callable $gc[, callable $create_sid[, callable $validate_sid[, callable $update_timestamp]]] ) : bool自 PHP 5.4 開始,可以使用下面的方式來注冊自定義會話存儲函數(shù):
session_set_save_handler( object $sessionhandler[, bool $register_shutdown = TRUE] ) : bool$sessionhandler實(shí)現(xiàn)了 SessionHandlerInterface, SessionIdInterface 和/或 SessionUpdateTimestampHandlerInterface 接口的對象,例如 SessionHandler。自 PHP 5.4 之后可以使用。
$register_shutdown將函數(shù) session_write_close() 注冊為 register_shutdown_function() 函數(shù)。
session_abort — Discard session array changes and finish session
session_abort()在不保存數(shù)據(jù)的情況下完成會話。這樣就保留了會話數(shù)據(jù)中的原始值。session_cache_expire — 返回當(dāng)前緩存的到期時間
session_cache_limiter — 讀取/設(shè)置緩存限制器
session_commit — session_write_close 的別名
-
session_create_id — Create new session id
用于為當(dāng)前會話創(chuàng)建newsession id。它返回?zé)o沖突的會話id。
session_decode — 解碼會話數(shù)據(jù)
session_encode — 將當(dāng)前會話數(shù)據(jù)編碼為一個字符串
session_gc — Perform session data garbage collection
session_get_cookie_params — 獲取會話 cookie 參數(shù)
session_is_registered — 檢查變量是否在會話中已經(jīng)注冊
session_module_name — 獲取/設(shè)置會話模塊名稱
session_register_shutdown — 關(guān)閉會話
session_register — Register one or more global variables with the current session
session_reset — Re-initialize session array with original values
session_set_cookie_params — 設(shè)置會話 cookie 參數(shù)
-
session_status — 返回當(dāng)前會話狀態(tài)
- PHP_SESSION_DISABLED 會話是被禁用的。
- PHP_SESSION_NONE 會話是啟用的,但不存在當(dāng)前會話。
- PHP_SESSION_ACTIVE 會話是啟用的,而且存在當(dāng)前會話。
session_unregister — Unregister a global variable from the current session
原文:
PHP函數(shù)參考22-session擴(kuò)展 - 9ong
PHP函數(shù)參考23-正則相關(guān)函數(shù) - 9ong