本篇內(nèi)容主要講解“php session的鎖和并發(fā)分別是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“php session的鎖和并發(fā)分別是什么”吧!
創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、溫泉網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5頁(yè)面制作、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)公司、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為溫泉等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。我登錄不了了
某天,我準(zhǔn)備登錄我們一個(gè)后臺(tái)系統(tǒng),前去解決一個(gè)bug,在賬戶密碼驗(yàn)證碼都準(zhǔn)確輸入的情況下,我登錄不上,經(jīng)過(guò)多次實(shí)驗(yàn)發(fā)現(xiàn)主要有兩個(gè)錯(cuò)誤信息:
csrf驗(yàn)證失敗
驗(yàn)證碼錯(cuò)誤【我對(duì)碼神起誓我用半角輸入了我看到的驗(yàn)證碼,且順序一致,無(wú)多加字符】
我們的系統(tǒng)
我們的系統(tǒng)是基于phalcon 2.0.8 開(kāi)發(fā)的,如你所見(jiàn),我們?cè)诒韱斡蚣尤肓朔乐筩srf攻擊的域。也啟用了驗(yàn)證碼。
<input type="hidden" name="{{ security.getTokenKey() }}" value="{{ security.getToken() }}"/> <img src="/login/getCaptcha" id="img-captcha"/>
我首先對(duì)這兩個(gè)組件進(jìn)行查閱,發(fā)現(xiàn)他們都是將數(shù)據(jù)存于session:
# phalcon/security.zep # Security::getToken() let session = <SessionInterface> dependencyInjector->getShared("session"); session->set(this->_tokenValueSessionID, token); $this->session->set('admin_get_captcha_action', $captcha);
然后我又查閱了我們session的實(shí)現(xiàn),發(fā)現(xiàn)是將數(shù)據(jù)存儲(chǔ)于redis的。
找啊找
什么問(wèn)題導(dǎo)致我登錄不上呢?既然是數(shù)據(jù)驗(yàn)證上出現(xiàn)問(wèn)題,就從數(shù)據(jù)著手吧,我登陸我們測(cè)試環(huán)境的redis機(jī)器,執(zhí)行 redis-cli monitor,然后走一遍登錄流程,發(fā)現(xiàn)輸出如下(意思意思):
GET sessionId
GET sessionId
SETEX sessionId 3600 csrf=xxxx
SETEX sessionId 3600 captcha=abcd
我們可以看到:
1、這里存在兩次請(qǐng)求,一次是表單加載,一次是生成驗(yàn)證碼的。
2、存在“并發(fā)”的情況,這兩個(gè)請(qǐng)求應(yīng)該是表單加載渲染后才請(qǐng)求驗(yàn)證碼的,也就是session順序應(yīng)該是get->set->get->set,看起來(lái)怎么是并發(fā)請(qǐng)求了。
3、后面那個(gè)SETEX沒(méi)有csrf的內(nèi)容,也就是覆蓋掉前面的數(shù)據(jù)了
整個(gè)世界都不好了,不過(guò)也稍微明白是什么問(wèn)題了。什么問(wèn)題呢,說(shuō)來(lái)話長(zhǎng),要從PHP的session數(shù)據(jù)的存取說(shuō)起。
php的session數(shù)據(jù)的存取
session的數(shù)據(jù)是經(jīng)過(guò)編碼成字符串存儲(chǔ)在存儲(chǔ)器【file、db、redis、memcache等】的,在我們使用session的時(shí)候,是什么時(shí)候去儲(chǔ)存器取數(shù)據(jù)的?又是什么時(shí)候?qū)?shù)據(jù)寫(xiě)入存儲(chǔ)器的?
這個(gè)問(wèn)題的答案可能和一些朋友想的不一樣,一個(gè)請(qǐng)求里面,PHP只會(huì)讀取一次存儲(chǔ)器,在session_start的時(shí)候,然后也只會(huì)寫(xiě)入一次存儲(chǔ)器,在請(qǐng)求結(jié)束的時(shí)候,或調(diào)用session_write_close的時(shí)候,將數(shù)據(jù)刷回存儲(chǔ)器,關(guān)閉session。
那么問(wèn)題來(lái)了:
1、如果一個(gè)會(huì)話,同時(shí)出現(xiàn)兩個(gè)讀寫(xiě)session請(qǐng)求,沒(méi)有保證獲取1-寫(xiě)入1-獲取2-寫(xiě)入2,同時(shí)沒(méi)有cas版本管理機(jī)制的情況下,這些并發(fā)請(qǐng)求就會(huì)彼此讀取不到對(duì)方的寫(xiě)入,最后寫(xiě)入的會(huì)把前面請(qǐng)求寫(xiě)入的session覆蓋掉。
2、如果請(qǐng)求是串行的,像登錄頁(yè)面的表單和驗(yàn)證碼,也有可能前面的請(qǐng)求已經(jīng)輸出內(nèi)容了,但是session還沒(méi)寫(xiě)入,后面的請(qǐng)求就已經(jīng)發(fā)起了。
鎖與不鎖
解決這種資源的并發(fā)一般會(huì)通過(guò)鎖或版本管理來(lái)處理。但是版本管理我看不到好的方法。就聊聊鎖吧。
其實(shí)鎖是不大適合,有弊端的。
php的session,默認(rèn)是用文件存儲(chǔ)的,在打開(kāi)session的時(shí)候,會(huì)對(duì)文件加獨(dú)占鎖,這樣,其它請(qǐng)求就無(wú)法獲取鎖了,只能等待直到前面的鎖解了。
這樣保證了 讀取-寫(xiě)入,讀取-寫(xiě)入的順序。
其它存儲(chǔ)器,例如mysql,可以借助select for update進(jìn)行行鎖。redis可以通過(guò)一個(gè)自增鍵,返回1的獲取到鎖等來(lái)實(shí)現(xiàn)。
這個(gè)實(shí)現(xiàn)的話,對(duì)數(shù)據(jù)流來(lái)說(shuō)很理想,但是,對(duì)于目前這種頁(yè)面大量應(yīng)用ajax的情況,所有請(qǐng)求排隊(duì)處理,將大大加大頁(yè)面展現(xiàn)的耗時(shí),甚至出現(xiàn)請(qǐng)求超時(shí)等不可用故障。
沒(méi)有解決的解決
不建議過(guò)多使用session,其一次讀取一次寫(xiě)入的機(jī)制所引發(fā)的問(wèn)題,會(huì)造成坑的存在。
在模版渲染前,或請(qǐng)求輸出前調(diào)用session_write_close
# 立刻回寫(xiě)session,避免session覆蓋 $eventManager = $this->view->getEventsManager(); if (!$eventManager) { $eventManager = new Manager(); $this->view->setEventsManager($eventManager); } $eventManager->attach("view:afterRender",function(){ session_write_close(); }); return $this->view;
if($login) { # 立刻回寫(xiě)session,避免session讀取不到 $eventManager = $this->dispatcher->getEventsManager(); if (!$eventManager) { $eventManager = new Manager(); $this->dispatcher->setEventsManager($eventManager); } $eventManager->attach('dispatch:afterDispatchLoop',function(){ session_write_close(); }); return $this->response->setHeader('Location', '/'); }
到此,相信大家對(duì)“php session的鎖和并發(fā)分別是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)建站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
分享文章:phpsession的鎖和并發(fā)分別是什么-創(chuàng)新互聯(lián)
標(biāo)題URL:http://muchs.cn/article28/dodccp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、企業(yè)網(wǎng)站制作、做網(wǎng)站、全網(wǎng)營(yíng)銷(xiāo)推廣、搜索引擎優(yōu)化、App開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容