PHP函數(shù)參考22-session擴(kuò)展



原文:
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)通信定制,對于安全,要重視再重視,先從會話安全開始,了解會話管理、會話問題、會話安全配置等:

PHP: 會話和安全 - Manual

  • 會話信息不安全,會話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)來釋放整個_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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容