成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP --- Session

stackfing / 1995人閱讀

摘要:服務(wù)器給訪問者唯一的鑰匙,這個(gè)鑰匙被稱作。與合起來用來管理垃圾回收進(jìn)程啟動(dòng)的概率。例如意味著在每個(gè)請(qǐng)求中有的概率啟動(dòng)進(jìn)程。值為表示直到關(guān)閉瀏覽器。過期時(shí)間設(shè)置為秒啟動(dòng)概率設(shè)置為

什么是 Session

在 web 應(yīng)用開發(fā)中,Session 被稱為會(huì)話。主要被用于保存某個(gè)訪問者的數(shù)據(jù)。
由于 HTTP 無狀態(tài)的特點(diǎn),服務(wù)端是不會(huì)記住客戶端的,對(duì)服務(wù)端來說,每一個(gè)請(qǐng)求都是全新的。
既然如此,那么服務(wù)端怎么知道是哪個(gè)訪問者在請(qǐng)求它呢?又如何將不同的數(shù)據(jù)對(duì)應(yīng)上正確的訪問者?答案是,給訪問者一個(gè)唯一獲取 Session 中數(shù)據(jù)的身份標(biāo)示。

打個(gè)比方:當(dāng)我們?nèi)コ匈徫飼r(shí),被保安告之我們是不能帶物品進(jìn)去的,必須將物品寄放在超市的儲(chǔ)物箱中。我們把物品交給了他,他怎么知道這些物品誰是誰的,于是他給了我們不同的鑰匙。當(dāng)我們要取走我們的物品時(shí),用唯一的鑰匙打開對(duì)應(yīng)的箱子即可。

就如同上面的比方一樣,可以將 Session 理解為存放我們數(shù)據(jù)的“箱子”,當(dāng)然,這些“箱子”都在服務(wù)端那。服務(wù)器給訪問者唯一的“鑰匙”,這個(gè)“鑰匙”被稱作 session_id。訪問者憑借自己的 session_id,就能獲取到自己存在服務(wù)器端的數(shù)據(jù)。

session_id 通過兩種方式傳給訪問者(客戶端):URL 或 cookie。詳情參見:傳送會(huì)話ID
Session 和 Cookie 有什么關(guān)系

Cookie 也是由于 HTTP 無狀態(tài)的特點(diǎn)而產(chǎn)生的技術(shù)。也被用于保存訪問者的身份標(biāo)示和一些數(shù)據(jù)。每次客戶端發(fā)起 HTTP 請(qǐng)求時(shí),會(huì)將 Cookie 數(shù)據(jù)加到 HTTP header 中,提交給服務(wù)端。這樣服務(wù)端就可以根據(jù) Cookie 的內(nèi)容知道訪問者的信息了。 可以說,Session 和 Cookie 做著相似的事情,只是 Session 是將數(shù)據(jù)保存在服務(wù)端,通過客戶端提交來的 session_id 來獲取對(duì)應(yīng)的數(shù)據(jù);而 Cookie 是將數(shù)據(jù)保存在客戶端,每次發(fā)起請(qǐng)求時(shí)將數(shù)據(jù)提交給服務(wù)端的。

上面提到,session_id 可以通過 URL 或 cookie 來傳遞,由于 URL 的方式比 cookie 的方式更加不安全且使用不方便,所以一般是采用 cookie 來傳遞 session_id。
服務(wù)端生成 session_id,通過 HTTP 報(bào)文發(fā)送給客戶端(比如瀏覽器),客戶端收到后按指示創(chuàng)建保存著 session_id 的 cookie。cookie 是以 key/value 形式保存的,看上去大概就這個(gè)樣子的:PHPSESSID=e4tqo2ajfbqqia9prm8t83b1f2。在 PHP 中,保存 session_id 的 cookie 名稱默認(rèn)叫作 PHPSESSID,這個(gè)名稱可以通過 php.ini 中 session.name 來修改,也可以通過函數(shù) session_name() 來修改。
為什么不推薦使用 PHP 自帶的 files 型 Session 處理器

在 PHP 中,默認(rèn)的 Session 處理器是 files,處理器可以用戶自己實(shí)現(xiàn)(參見:自定義會(huì)話管理器)。我知道的成熟的 Session 處理器還有很多:Redis、Memcached、MongoDB……
為什么不推薦使用 PHP 自帶的 files 類型處理器,PHP 官方手冊(cè)中給出過這樣一段 Note:

無論是通過調(diào)用函數(shù) session_start() 手動(dòng)開啟會(huì)話, 還是使用配置項(xiàng) session.auto_start 自動(dòng)開啟會(huì)話, 對(duì)于基于文件的會(huì)話數(shù)據(jù)保存(PHP 的默認(rèn)行為)而言, 在會(huì)話開始的時(shí)候都會(huì)給會(huì)話數(shù)據(jù)文件加鎖, 直到 PHP 腳本執(zhí)行完畢或者顯式調(diào)用 session_write_close() 來保存會(huì)話數(shù)據(jù)。 在此期間,其他腳本不可以訪問同一個(gè)會(huì)話數(shù)據(jù)文件。

上述引用參見:Session 的基本用法

為了證明這段話,我們創(chuàng)建一下 2 個(gè)文件: 文件:session1.php

session_start();

sleep(5);

var_dump($_SESSION);
?>

文件:session2.php

session_start();

var_dump($_SESSION);
?>

在同一個(gè)瀏覽器中,先訪問 http://127.0.0.1/session1.php,然后在當(dāng)前瀏覽器新的標(biāo)簽頁立刻訪問 http://127.0.0.1/session2.php。實(shí)驗(yàn)發(fā)現(xiàn),session1.php 等了 5 秒鐘才有輸出,而 session2.php 也等到了將近 5 秒才有輸出。而多帶帶訪問 session2.php 是秒開的。在一個(gè)瀏覽器中訪問 session1.php,然后立刻在另外一個(gè)瀏覽器中訪問 session2.php。結(jié)果是 session1.php 等待 5 秒鐘有輸出,而 session2.php 是秒開的。

分析一下造成這個(gè)現(xiàn)象的原因:上面例子中,默認(rèn)使用 Cookie 來傳遞 session_id,而且 Cookie 的作用域是相同。這樣,在同一個(gè)瀏覽器中訪問這 2 個(gè)地址,提交給服務(wù)器的 session_id 就是相同的(這樣才能標(biāo)記訪問者,這是我們期望的效果)。當(dāng)訪問 session1.php 時(shí),PHP 根據(jù)提交的 session_id,在服務(wù)器保存 Session 文件的路徑(默認(rèn)為 /tmp,通過 php.ini 中的 session.save_path 或者函數(shù) session_save_path() 來修改)中找到了對(duì)應(yīng)的 Session 文件,并對(duì)其加鎖。如果不顯式調(diào)用 session_write_close(),那么直到當(dāng)前 PHP 腳本執(zhí)行完畢才會(huì)釋放文件鎖。如果在腳本中有比較耗時(shí)的操作(比如例子中的 sleep(5)),那么另一個(gè)持有相同 session_id 的請(qǐng)求由于文件被鎖,所以只能被迫等待,于是就發(fā)生了請(qǐng)求阻塞的情況。

既然如此,在使用完 Session 后,立刻顯示調(diào)用 session_write_close() 是不是就解決問題了哩?比如上面例子中,在 sleep(5) 前面調(diào)用 session_write_close()。
確實(shí),這樣 session2.php 就不會(huì)被 session1.php 所阻塞。但是,顯示調(diào)用了 session_write_close() 就意味著將數(shù)據(jù)寫到文件中并結(jié)束當(dāng)前會(huì)話。那么,在后面代碼中要使用 Session 時(shí),必須重新調(diào)用 session_start()。

例如:

session_start();
$_SESSION["name"] = "Jing";
var_dump($_SESSION);
session_write_close();

sleep(5);

session_start();
$_SESSION["name"] = "Mr.Jing";
var_dump($_SESSION);
?>

官方給出的方案:

對(duì)于大量使用 Ajax 或者并發(fā)請(qǐng)求的網(wǎng)站而言,這可能是一個(gè)嚴(yán)重的問題。 解決這個(gè)問題最簡單的做法是如果修改了會(huì)話中的變量, 那么應(yīng)該盡快調(diào)用 session_write_close() 來保存會(huì)話數(shù)據(jù)并釋放文件鎖。 還有一種選擇就是使用支持并發(fā)操作的會(huì)話保存管理器來替代文件會(huì)話保存管理器。

我推薦的方式是使用 Redis 作為 Session 的處理器。

拓展閱讀:

為什么不能用 memcached 存儲(chǔ) Session

如何使用 Redis 作為 PHP Session handler
Session 數(shù)據(jù)是什么時(shí)候被刪除的

這是一道經(jīng)常被面試官問起的問題。

先看看官方手冊(cè)中的說明:

session.gc_maxlifetime 指定過了多少秒之后數(shù)據(jù)就會(huì)被視為"垃圾"并被清除。 垃圾搜集可能會(huì)在 session 啟動(dòng)的時(shí)候開始( 取決于 session.gc_probability 和 session.gc_divisor)。 session.gc_probability 與 session.gc_divisor 合起來用來管理 gc(garbage collection 垃圾回收)進(jìn)程啟動(dòng)的概率。此概率用 gc_probability/gc_divisor 計(jì)算得來。例如 1/100 意味著在每個(gè)請(qǐng)求中有 1% 的概率啟動(dòng) gc 進(jìn)程。session.gc_probability 默認(rèn)為 1,session.gc_divisor 默認(rèn)為 100。

繼續(xù)用我上面那個(gè)不太恰當(dāng)?shù)谋确桨桑喝绻覀儼盐锲贩旁诔械膬?chǔ)物箱中而不取走,過了很久(比如一個(gè)月),那么保安就要清理這些儲(chǔ)物箱中的物品了。當(dāng)然并不是超過期限了保安就一定會(huì)來清理,也許他懶,又或者他壓根就沒有想起來這件事情。

再看看兩段手冊(cè)的引用:

如果使用默認(rèn)的基于文件的會(huì)話處理器,則文件系統(tǒng)必須保持跟蹤訪問時(shí)間(atime)。Windows FAT 文件系統(tǒng)不行,因此如果必須使用 FAT 文件系統(tǒng)或者其他不能跟蹤 atime 的文件系統(tǒng),那就不得不想別的辦法來處理會(huì)話數(shù)據(jù)的垃圾回收。自 PHP 4.2.3 起用 mtime(修改時(shí)間)來代替了 atime。因此對(duì)于不能跟蹤 atime 的文件系統(tǒng)也沒問題了。

GC 的運(yùn)行時(shí)機(jī)并不是精準(zhǔn)的,帶有一定的或然性,所以這個(gè)設(shè)置項(xiàng)并不能確保舊的會(huì)話數(shù)據(jù)被刪除。某些會(huì)話存儲(chǔ)處理模塊不使用此設(shè)置項(xiàng)。

對(duì)于這種刪除機(jī)制,我是存疑的。

比如 gc_probability/gc_divisor 設(shè)置得比較大,或者網(wǎng)站的請(qǐng)求量比較大,那么 GC 進(jìn)程啟動(dòng)就會(huì)比較頻繁。
還有,GC 進(jìn)程啟動(dòng)后都需要遍歷 Session 文件列表,對(duì)比文件的修改時(shí)間和服務(wù)端的當(dāng)前時(shí)間,判斷文件是否過期而決定是否刪除文件。
這也是我覺得不應(yīng)該使用 PHP 自帶的 files 型 Session 處理器的原因。而 Redis 或 Memcached 天生就支持 key/value 過期機(jī)制的,用于作為會(huì)話處理器很合適?;蛘咦约簩?shí)現(xiàn)一個(gè)基于文件的處理器,當(dāng)根據(jù) session_id 獲取對(duì)應(yīng)的單個(gè) Session 文件時(shí)判斷文件是否過期。
為什么重啟瀏覽器后 Session 數(shù)據(jù)就取不到了

session.cookie_lifetime 以秒數(shù)指定了發(fā)送到瀏覽器的 cookie 的生命周期。值為 0 表示"直到關(guān)閉瀏覽器"。默認(rèn)為 0。

其實(shí),并不是 Session 數(shù)據(jù)被刪除(也有可能是,概率比較小,參見上一節(jié))。只是關(guān)閉瀏覽器時(shí),保存 session_id 的 Cookie 沒有了。也就是你弄丟了打開超市儲(chǔ)物箱的鑰匙(session_id)。

同理,瀏覽器 Cookie 被手動(dòng)清除或者其他軟件清除也會(huì)造成這個(gè)結(jié)果。
為什么瀏覽器開著,我很久沒有操作就被登出了

這個(gè)是稱為“防呆”,為了保護(hù)用戶賬戶安全的。

這個(gè)小節(jié)放進(jìn)來,是因?yàn)檫@個(gè)功能的實(shí)現(xiàn)可能和 Session 的刪除機(jī)制有關(guān)(之所以說是可能,是因?yàn)檫@個(gè)功能不一定要借住 Session 實(shí)現(xiàn),用 Cookie 也同樣可以實(shí)現(xiàn))。 說簡單一點(diǎn),就是長時(shí)間沒有操作,服務(wù)端的 Session 文件過期被刪除了。
一個(gè)有意思的事情

在我試驗(yàn)的過程中,發(fā)現(xiàn)了小有意思的事情:我把 GC 啟動(dòng)的概率設(shè)置為 100%。如果只有一個(gè)訪問者請(qǐng)求,該訪問者即使過了很久(超過了過期時(shí)間)后才發(fā)起第二次請(qǐng)求,那么 Session 數(shù)據(jù)也還是存在的("session.save_path" 目錄下面的 Session 文件存在)。是的,明明就超過了過期時(shí)間,卻沒有被 GC 刪除。這時(shí),我用另外一個(gè)瀏覽器訪問時(shí)(相對(duì)于另一個(gè)訪問者),這次請(qǐng)求生成了新的 Session 文件,而上一個(gè)瀏覽器請(qǐng)求生成的那個(gè) Session 文件終于沒有了(之前那個(gè) Session 文件在 "session.save_path" 目錄下面的消失了)。

還有,發(fā)現(xiàn) Session 文件被刪除后,再次請(qǐng)求,還是會(huì)生成和之前文件名相同的 Session 文件(因?yàn)闉g覽器并沒有關(guān)閉,再次請(qǐng)求發(fā)送的 session_id 是相同的,所以重新生成的 Session 文件的文件名還是一樣的)。但是,我不理解的是:這個(gè)重新出現(xiàn)的文件的創(chuàng)建時(shí)間竟然是第一次的那個(gè)創(chuàng)建時(shí)間,難道它是從回收站中回來的?(確實(shí),我做這個(gè)試驗(yàn)時(shí)是在 window 下進(jìn)行的)

我猜測的原因是這樣:當(dāng)啟動(dòng)會(huì)話后,PHP 根據(jù) session_id 找到并打開了對(duì)應(yīng)的 Session 文件,然后才啟動(dòng) GC 進(jìn)程。GC 進(jìn)程就只檢查除了當(dāng)前這個(gè) Session 文件外的其他文件,發(fā)現(xiàn)過期的就干掉。所有,即使當(dāng)前這個(gè) Session 文件已經(jīng)過期了,GC 也沒有刪除它。

我認(rèn)為這個(gè)不合理的。

由于發(fā)生這種情況影響也不大(畢竟線上請(qǐng)求很多,當(dāng)前請(qǐng)求的過期文件被其他請(qǐng)求喚起的 GC 干掉的可能性是比較大的) + 我沒有信心去看 PHP 源代碼 + 我并不在線上使用 PHP 自帶的 files 型 Session 處理器。所以,這個(gè)問題我就沒有深入研究了。請(qǐng)諒解。

// 過期時(shí)間設(shè)置為 30 秒
ini_set("session.gc_maxlifetime", "30");

// GC 啟動(dòng)概率設(shè)置為 100%
ini_set("session.gc_probability", "100");
ini_set("session.gc_divisor", "100");

session_start();
$_SESSION["name"] = "Jing";

var_dump($_SESSION);
?>

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/22759.html

相關(guān)文章

  • lamp 將session保存到Redis

    摘要:需要修改以下三個(gè)地方修改安裝擴(kuò)展修改的如果是也有需要修改相關(guān)的配置配置文件影響配置項(xiàng)有要將保存到,,必須要配置的。配置完以后,可能不生效。通過會(huì)看到配置里有兩個(gè)值,,。受配置文件配置影響受的影響。它們的配置優(yōu)先級(jí)比高,會(huì)覆蓋中的配置。 需要修改以下三個(gè)地方:1、修改php.ini2、安裝phpredis擴(kuò)展3、修改apache的php.conf4、如果是php-fpm也有需要修改相關(guān)的...

    khlbat 評(píng)論0 收藏0
  • 關(guān)于 PHPSession 的幾個(gè)問題

    摘要:主要被用于保存某個(gè)訪問者的數(shù)據(jù)。服務(wù)器給訪問者唯一的鑰匙,這個(gè)鑰匙被稱作。例如官方給出的方案對(duì)于大量使用或者并發(fā)請(qǐng)求的網(wǎng)站而言,這可能是一個(gè)嚴(yán)重的問題。例如意味著在每個(gè)請(qǐng)求中有的概率啟動(dòng)進(jìn)程。因此對(duì)于不能跟蹤的文件系統(tǒng)也沒問題了。 什么是 Session 在 web 應(yīng)用開發(fā)中,Session 被稱為會(huì)話。主要被用于保存某個(gè)訪問者的數(shù)據(jù)。 由于 HTTP 無狀態(tài)的特點(diǎn),服務(wù)端是不會(huì)記...

    CoyPan 評(píng)論0 收藏0
  • [PHP 安全] OWASP 維護(hù)的 PHP 安全配置速查表

    摘要:文章轉(zhuǎn)自介紹這個(gè)頁面的目的是為了幫助那些配置和運(yùn)行它的服務(wù)器的人確保它的安全性。下面你將找到有關(guān)文件的正確配置信息。最后,查看文檔以獲得關(guān)于配置文件中每個(gè)值的參考。 showImg(https://segmentfault.com/img/remote/1460000018821916?w=1520&h=550); 文章轉(zhuǎn)自:https://learnku.com/php/t/2697...

    dabai 評(píng)論0 收藏0
  • phpsession的相關(guān)設(shè)置描述

    摘要:一下大多是網(wǎng)上的資料,自己只是整理了下,如果有錯(cuò)誤希望能指出,感謝中的相關(guān)配置先看下中的相關(guān)配置的解釋。啟用此設(shè)定可以防止有關(guān)通過傳遞會(huì)話的攻擊。值為表示直到關(guān)閉瀏覽器。例如意味著在每個(gè)請(qǐng)求中有的概率啟動(dòng)進(jìn)程。 對(duì)于session的了解,之前一直沒有仔細(xì)研究過,最近遇到了一些問題,需要解決session配置問題,就順便查看了些資料。一下大多是網(wǎng)上的資料,自己只是整理了下,如果有錯(cuò)誤希望...

    jsdt 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<