- 相關(guān)推薦
HTTP會話原理解釋與應(yīng)用
導(dǎo)語:通過會話管理能夠?qū)掃M(jìn)行創(chuàng)建、信息存儲、關(guān)閉。下面就由小編為大家介紹一下HTTP會話原理解釋與應(yīng)用,歡迎大家閱讀!
一、什么是會話
首先解釋一下什么是會話。在計算機(jī)術(shù)語中,會話是指一個終端用戶與交互系統(tǒng)進(jìn)行通訊的過程,比如從輸入賬戶密碼進(jìn)入操作系統(tǒng)到退出操作系統(tǒng)就是一個會話過程。會話較多用于網(wǎng)絡(luò)上,TCP的三次握手就創(chuàng)建了一個會話,TCP關(guān)閉連接就是關(guān)閉會話。用平述的語言可以解釋為:你拔打你女友的電話號碼,你女友接聽,然后一翻“親愛的”,直到任何一方掛掉電話,這個過程就是一個會話。你挑逗一只小狗,它跟你互動,也是會話;它不鳥你,那就不形成會話。
二、什么是HTTP會話
協(xié)議的狀態(tài)是指下一次傳輸可以“記住”這次傳輸信息的能力,HTTP是不會為了下一次連接而維護(hù)這次連接所傳輸?shù)男畔⒌。從傳統(tǒng)WEB上看:無狀態(tài)是指,當(dāng)瀏覽器發(fā)送請求給服務(wù)器的時候,服務(wù)器響應(yīng),但是同一個瀏覽器再發(fā)送請求給服務(wù)器的時候,他會響應(yīng),但是他不知道你就是剛才那個瀏覽器,簡單地說,就是服務(wù)器不會去記得你,所以是無狀態(tài)協(xié)議。本質(zhì)是:HTTP1.0是短連接的(這里先忽略HTTP1.1的keep alive吧),請求響應(yīng)后,斷開了TCP連接,下一次連接與上一次無關(guān)。為了識別不同的請求是否來自同一客戶,引用HTTP會話機(jī)制,即:多次HTTP連接間維護(hù)用戶與同一用戶發(fā)出的不同請求之間關(guān)聯(lián)的情況稱為維護(hù)一個會話(session)。通過會話管理對會話進(jìn)行創(chuàng)建、信息存儲、關(guān)閉等。
三、HTTP會話的實現(xiàn)機(jī)制
Cookie與session是各種教材,網(wǎng)上文章所介紹到的與HTTP會話相關(guān)的兩個內(nèi)容。這種者較常見的解釋是:cookie存在在瀏覽器,session存儲在服務(wù)器中。這種解釋是最顯淺的,很不嚴(yán)謹(jǐn),但又不能說是錯誤。先從cookie談起吧,很久很久以前,為了完成HTTP會話,那些互聯(lián)網(wǎng)的設(shè)計者們想到了一個辦法,就是在瀏覽器中存儲用戶信息,每次請求都向服務(wù)端發(fā)送這些信息,這樣服務(wù)端就知道請求發(fā)送者是誰了,就知道應(yīng)該返回什么信息給客戶了。但是問題很快就出現(xiàn)了,張三冒充李四的名字發(fā)送請求給服務(wù)器,服務(wù)器把李四的相關(guān)信息發(fā)給了張三。為了安全起見,互聯(lián)網(wǎng)老大哥們又想到了一招識別用戶身份的辦法,就是把客戶信息存儲在服務(wù)端(session),一切用戶的身份由服務(wù)器指定。直到目前,session已成功HTTP會話的主流,應(yīng)該說是絕對控制的地位。
Session是怎樣做到會話身份識別的呢?首先,用戶端向服務(wù)端發(fā)送一個請求,服務(wù)端接收到請求(這里忽悠無須會話控制的情況)后,初始化會話,生成相應(yīng)的會話信息,核心是會話ID,把會話ID發(fā)送給客戶端,客戶端接收到這個會話ID,把它存儲起來,下一次發(fā)送請求的時候,附帶著這個會話ID一起發(fā)送給服務(wù)端,服務(wù)端只要根據(jù)這個會話ID,就知道是誰了。這個會話ID,就像我們的身份證號碼,一直伴隨終生。核心:服務(wù)端如何生成這個會話ID,客戶端怎樣存儲這個會話ID。
四、如何存儲會話ID(SESSION ID)
服務(wù)端存儲會話ID有多種方式,常見的有本地存儲,如:普通文本,文本名就是會話ID。對于文件系統(tǒng),同一目錄下,同一文件名只允許唯一一個文件,那么使用會話ID作為文件名是可以做到唯一確定會話的。除了本地文件存儲,還可以使用memcache、redis、或者M(jìn)ysql之類的數(shù)據(jù)庫存儲,即使用第三方數(shù)據(jù)庫進(jìn)行存儲。只有一個原則:存儲的會話ID必須是唯一的。
客戶端收到服務(wù)端返回的(或者說服務(wù)端下發(fā)的)會話ID后,也是像服務(wù)端那樣使用文件名作為會話ID存儲會話信息到文本嗎?如果客戶端只與同一個服務(wù)端(理解為同一個服務(wù)端處理程序)進(jìn)行會話通訊的話,是可行的。但是,HTTP是因萬維網(wǎng)而生的,瀏覽器作為最常見的HTTP客戶端,需要訪問各種不同的網(wǎng)站,如果采用會話ID作為文件名,以這樣的文件存在會話信息的話,會出現(xiàn)這樣的情況:N個不同的網(wǎng)站,服務(wù)端采用的是相同的會話生成算法,在同一時刻,很可能會生成一樣的會話ID,客戶端則無法唯一確定這個會話ID到底是與哪個服務(wù)端通訊,也就是客戶端“不認(rèn)得”服務(wù)端了,會話就無法完成。如何確定服務(wù)端身份?那就是使用“域”,不同的域擁有獨立的會話?蛻舳艘杂蛳嚓P(guān)信息作為文件標(biāo)識符創(chuàng)建會話文件(客戶端存儲)對會話信息進(jìn)行存儲,其中域與會話ID結(jié)合就能唯一確定服務(wù)端,并且確定會話。那么,以“域”信息作為文件名的文件中存儲著會話ID等信息。每次請求某個域的服務(wù)時,把存儲著的會話ID附帶到請求中發(fā)送到服務(wù)端。瀏覽器是最常見的HTTP客戶端,瀏覽器存儲會話信息,是使用COOKIE文件的,里面保存著COOKIE信息,而服務(wù)端返回的會話ID也存儲在里面。會話ID存儲在COOKIE文件中是一般情況下的,而COOKIE信息是作為HTTP頭發(fā)送給服務(wù)端的,也就是說這種情況下,會話ID是附帶在請求頭中。但是,HTTP請求,除了頭信息,還可以有內(nèi)容體,必須有URL。那么,會話ID同樣可以存儲在內(nèi)容體中或URL中,比如在禁用瀏覽器COOKIE的情況下,也可實現(xiàn)與服務(wù)端會話,要么依賴內(nèi)容體,要么依賴URL,常見的是URL中附帶會話ID,這個在PHP等編程語言中較為常見(曾經(jīng)的歷史上常見,但是會涉及安全或者效率等問題,這里不詳述)。
粗糙地,可理解為服務(wù)端返回給客戶端的會話ID是存儲在COOKIE文件中的。COOKIE文件是由瀏覽器管理的,當(dāng)然在自實現(xiàn)的客戶端中,可以通過編程手段實現(xiàn)COOKIE文件管理,即客戶端會話的管理。舉例:IOS開發(fā)者,可以把HTTP返回的信息頭存儲到沙盒中進(jìn)行管理。PHP開發(fā)客戶端時,可以把信息頭寫到文件中,或第三方服務(wù)中,或網(wǎng)絡(luò)存儲中等等。
五、會話管理(SESSION)
會話管理包括:會話創(chuàng)建、會話識別、會話信息操作、會話生命周期、會話關(guān)閉。
注意:這一節(jié)中的服務(wù)端會話都看作是開啟的,無特別情況不再交待。
1、會話創(chuàng)建
客戶端發(fā)起不帶會話ID(SESSION ID)的HTTP請求,服務(wù)端認(rèn)為還沒產(chǎn)生會話,即創(chuàng)建會話,生成會話ID并且在服務(wù)器中存儲相關(guān)會話信息,并通知客戶端已開啟會話。一般情況下,是在返回給客戶端的HTTP header中的COOKIE項中附帶上會話ID,形式為:會話標(biāo)記:會話ID。客戶端根據(jù)返回的信息頭,設(shè)置本地COOKIE值并存儲。
2、會話識別
會話ID是會話的唯一標(biāo)識符,一個會話ID只會對應(yīng)一個會話,就像身份證號碼只對應(yīng)一個人一樣。HTTP中,服務(wù)端是被動接受請求的,會話識別也是被動的(觸發(fā)式)。服務(wù)端不需要知道發(fā)送請求的到底是誰,只需要知道對方發(fā)送過來的會話ID,把客戶端傳過來的會話ID與服務(wù)端存儲的會話ID進(jìn)行匹配。找不到這個會話ID,就認(rèn)為這個會話是不存在的。
舉例:服務(wù)器有個會話ID是“21412545jladfjljljqwr”,映射的值是“名字:張三,性別:男”?蛻舳酥灰埱笾械臅扞D是“21412545jladfjljljqwr”,就識別到這個會話了,能認(rèn)為這人是張三,而且是男性。如果客戶端請求的會話ID是“qwesadfasdfadsfasdf”,即使客戶端附帶了信息“名字:張三,性別:男”,服務(wù)端都認(rèn)為不存在此人,不形成會話。就算是李四盜用了張三的會話ID,服務(wù)端也會識別這個會話。
可簡單理解為:SESSION只根據(jù)SESSION ID建立起會話,是不負(fù)責(zé)安全校驗的,只負(fù)責(zé)讓服務(wù)端與客戶端可以“通話”。
3、會話信息操作
服務(wù)端:會話ID映射信息,ID不變,映射的內(nèi)容可變
客戶端:會話ID映射信息,ID不變,映射的內(nèi)容可變(即存在在COOKIEk中的內(nèi)容可變)。
服務(wù)端與客戶端的會話信息只有會話ID是必須相同的,其它會話信息(即會話ID映射的信息)沒有直接關(guān)系。
4、會話生命周期
會話從開始到結(jié)束就是會話的生命周期。設(shè)定一個時間,這個時間內(nèi)無通訊就清除會話信息,我們就把這個時間叫做會話超時周期。
習(xí)慣地,我們把會話超時周期叫做會話的生命周期,其實這是兩個概念。
5、會話關(guān)閉
會話關(guān)閉,有2種方式。一種是用戶主動清除會話信息,另一種是會話超時。會話超時不是守護(hù)任務(wù)(或自動任務(wù))周期性檢查處理的,而是訪問會話信息時,根據(jù)會話信息中的“上一次更新時間”到現(xiàn)在的時間差,與會話周期比較,超出周期的,清除會話信息,即會話關(guān)閉。
經(jīng)典例子:會話過程中,突然斷網(wǎng)。
六、會話校驗與HTTP協(xié)議冪等性
HTTP冪等性簡述:
從定義上看,HTTP方法的冪等性是指一次和多次請求某一個資源應(yīng)該具有同樣的副作用。冪等性屬于語義范疇,正如編譯器只能幫助檢查語法錯誤一樣,HTTP規(guī)范也沒有辦法通過消息格式等語法手段來定義它,這可能是它不太受到重視的原因之一。但實際上,冪等性是分布式系統(tǒng)設(shè)計中十分重要的概念,而HTTP的分布式本質(zhì)也決定了它在HTTP中具有重要地位。
舉個例子(摘抄網(wǎng)上):假設(shè)有一個從賬戶取錢的遠(yuǎn)程API(可以是HTTP的,也可以不是),我們暫時用類函數(shù)的方式記為:bool withdraw(account_id, amount)。請求服務(wù)端,減小account_id的amount金額,成功返回true;失敗金額不變,返回false。
如果服務(wù)端成功了,并返回true,但網(wǎng)絡(luò)中斷,客戶端收不到信息,客戶端認(rèn)為取錢失敗,再次請求,服務(wù)端再一次扣費。這里就涉及一個重復(fù)請求同一操作的問題了。
要解決這個問題,我們可以把withdraw設(shè)計為冪等的。create_ticket的語義是獲取一個服務(wù)器端生成的唯一的處理號ticket_id,它將用于標(biāo)識后續(xù)的操作。idempotent_withdraw和withdraw的區(qū)別在于關(guān)聯(lián)了一個ticket_id,一個ticket_id表示的操作至多只會被處理一次,每次調(diào)用都將返回第一次調(diào)用時的處理結(jié)果。這樣,idempotent_withdraw就符合冪等性了,客戶端就可以放心地多次調(diào)用。
從上面例子可以看到create_cicket的作用是生成ID識別碼,后續(xù)操作均基于此ID。會話ID本質(zhì)上也是冪等性的,生成ID后,后續(xù)操作均帶上ID參數(shù),即建立操作信息與ID的對應(yīng)關(guān)系。上面的例子并不是安全的,只是確保了操作對于同一個人(一次會話過程)是唯一的。同樣,會話ID只作為身份唯一的識別,不是安全的保證。
簡單會話校驗:
一種較簡單的會話校驗是使用令牌,即請求中除了會話ID,至少還攜帶了令牌。服務(wù)端對令牌校驗。令牌由服務(wù)端根據(jù)某種算法生成,令牌校驗也在服務(wù)端中處理,客戶端只需存儲令牌,在請求中攜帶令牌,令牌生成算法的復(fù)雜程度影響令牌校驗的安全性。
舉例:tokenFunc(param,value=’’) 第一個參數(shù)為令牌生成參數(shù),第二個參數(shù)為Token值。當(dāng)?shù)诙䥇?shù)為空時,成生Token,返回string;第二個參數(shù)不為空時,檢查Token準(zhǔn)確性 ,返回bool. 一般不需要解密,只要散列加密即可。PHP代碼如下:
function token($param,$value=’’){
if(!is_string($param){
$param = serialize($param);
}
$token = md5($param.’sault’);
if(!empty($value)){
if($value == $token){
return true;
}else{
return false;
}
}else{
return $token;
}
}
生成令牌:$token = token($session_id);
檢驗令牌:$check = token($session_id,$token);
七、會話原理的應(yīng)用
瀏覽器默認(rèn)是開啟Cookie的,瀏覽器發(fā)起HTTP請求時,在請求頭中帶有Cookie信息,只要服務(wù)端返回Cookie中包含SessionID,在服務(wù)端根據(jù)Sessionid即實現(xiàn)HTTP會話,此過程對于前端開發(fā)者是透明的(即前端開發(fā)可以不關(guān)心瀏覽器是怎樣與服務(wù)端確定會話的)。
除即時通訊,實時動作網(wǎng)游外,大多APP是使用HTTP協(xié)議與服務(wù)端通訊的,使用HTTP協(xié)議的原因主要是移動網(wǎng)絡(luò)環(huán)境復(fù)雜(容易斷線),并且HTTP協(xié)議穿透性強。原生開發(fā)的IOS,安卓等APP,與服務(wù)端會話,可不使用COOKIE,只需要在請求中攜帶會話ID即可,這在上文已描述。原生APP與內(nèi)嵌瀏覽器的APP相比:原生實現(xiàn)性能更高,交互效果流暢,用戶體驗相對較好,但快速跌代比不上內(nèi)嵌瀏覽器的APP。手機(jī)配置越來越高,內(nèi)嵌瀏覽器對HTML5支持也越來越好,在性能要求不是很高的場景,內(nèi)嵌WEB的性能已可滿足,在布局多變,或者元素多變的情況下,可快速修改,而無需用戶升級APP,也能獲得更好的產(chǎn)品體驗。APP內(nèi)嵌WEB最常見的場景就是電商APP了,登陸、注冊、入口等交互效果較多的模塊使用原生程序開發(fā),而商品列表、商品展示等等模塊可采用內(nèi)嵌WEB,這樣既可滿足快速產(chǎn)品跌代的要求,又可滿足操作的性能要求。
舉例:電商APP入門界面、登陸、注冊是使用原生開發(fā)的,登陸后跳轉(zhuǎn)到商品列表頁(即內(nèi)嵌WEB),然后下訂單。問題來了,如何使得登陸后跳轉(zhuǎn)到WEB后,還是登陸狀態(tài)(即內(nèi)嵌WEB與原生程序具有一致的會話)呢?內(nèi)嵌WEB是不會去取得原生程序所存儲的data的。最簡單直接的辦法就是:登陸成功,服務(wù)器返回會話ID與成功信息,跳轉(zhuǎn)到WEB時,發(fā)送的HTTP請求頭中包括COOKIE,會話ID存儲在COOKIE中,這樣之后點擊WEB中的鏈接后向服務(wù)端發(fā)送的HTTP請求頭,就會攜帶這個COOKIE(會話ID)了。簡單地理解:終端原生程序請求服務(wù)端,服務(wù)端按普通WEB那樣返回信息,終端原生程序取得HTTP返回頭中的COOKIE信息,保存下來,下一次請求時,攜帶COOKIE信息即可。在瀏覽器中,COOKIE的處理由瀏覽器默認(rèn)處理,而在原生APP程序中,由開發(fā)者寫程序去處理而已。
【HTTP會話原理解釋與應(yīng)用】相關(guān)文章:
網(wǎng)頁設(shè)計中的數(shù)學(xué)原理應(yīng)用03-05
JAVA如何獲取HTTP請求頭02-14
關(guān)于計算機(jī)原理中C語言的應(yīng)用06-02
PHP實現(xiàn)HTTP斷點續(xù)傳的方法07-10