Cookie / Session 的机制与安全
前些天發(fā)現(xiàn)了一個巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點擊跳轉(zhuǎn)到教程。
Cookie和Session是為了在無狀態(tài)的HTTP協(xié)議之上維護(hù)會話狀態(tài),使得服務(wù)器可以知道當(dāng)前是和哪個客戶在打交道。本文來詳細(xì)討論Cookie和Session的實現(xiàn)機(jī)制,以及其中涉及的安全問題。
因為HTTP協(xié)議是無狀態(tài)的,即每次用戶請求到達(dá)服務(wù)器時,HTTP服務(wù)器并不知道這個用戶是誰、是否登錄過等。現(xiàn)在的服務(wù)器之所以知道我們是否已經(jīng)登錄,是因為服務(wù)器在登錄時設(shè)置了瀏覽器的Cookie!Session則是借由Cookie而實現(xiàn)的更高層的服務(wù)器與瀏覽器之間的會話。
Cookie是由網(wǎng)景公司的前雇員Lou Montulli在1993年發(fā)明的,現(xiàn)今Cookie已經(jīng)廣泛使用了。
Cookie 的實現(xiàn)機(jī)制
Cookie是由客戶端保存的小型文本文件,其內(nèi)容為一系列的鍵值對。?Cookie是由HTTP服務(wù)器設(shè)置的,保存在瀏覽器中, 在用戶訪問其他頁面時,會在HTTP請求中附上該服務(wù)器之前設(shè)置的Cookie。 Cookie的實現(xiàn)標(biāo)準(zhǔn)定義在RFC2109: HTTP State Management Mechanism中。 那么Cookie是怎樣工作的呢?下面給出整個Cookie的傳遞流程:
對應(yīng)的服務(wù)器收到該HTTP請求,并計算應(yīng)當(dāng)返回給瀏覽器的HTTP響應(yīng)。
HTTP響應(yīng)包括請求頭和請求體兩部分,可以參見:讀 HTTP 協(xié)議。
在響應(yīng)頭加入Set-Cookie字段,它的值是要設(shè)置的Cookie。
在RFC2109 6.3 Implementation Limits中提到: UserAgent(瀏覽器就是一種用戶代理)至少應(yīng)支持300項Cookie, 每項至少應(yīng)支持到4096字節(jié),每個域名至少支持20項Cookie。
瀏覽器在響應(yīng)頭中發(fā)現(xiàn)Set-Cookie字段,就會將該字段的值保存在內(nèi)存或者硬盤中。
Set-Cookie字段的值可以是很多項Cookie,每一項都可以指定過期時間Expires。 默認(rèn)的過期時間是用戶關(guān)閉瀏覽器時。
瀏覽器下次給該服務(wù)器發(fā)送HTTP請求時, 會將服務(wù)器設(shè)置的Cookie附加在HTTP請求的頭字段Cookie中。
瀏覽器可以存儲多個域名下的Cookie,但只發(fā)送當(dāng)前請求的域名曾經(jīng)指定的Cookie, 這個域名也可以在Set-Cookie字段中指定)。
服務(wù)器收到這個HTTP請求,發(fā)現(xiàn)請求頭中有Cookie字段, 便知道之前就和這個用戶打過交道了。
總之,服務(wù)器通過Set-Cookie響應(yīng)頭字段來指示瀏覽器保存Cookie, 瀏覽器通過Cookie請求頭字段來告訴服務(wù)器之前的狀態(tài)。 Cookie中包含若干個鍵值對,每個鍵值對可以設(shè)置過期時間。
Cookie 的安全隱患
Cookie提供了一種手段使得HTTP請求可以附加當(dāng)前狀態(tài), 現(xiàn)今的網(wǎng)站也是靠Cookie來標(biāo)識用戶的登錄狀態(tài)的:
這里面的問題在哪里?
我們知道可以發(fā)送HTTP請求的不只是瀏覽器,很多HTTP客戶端軟件(包括curl、Node.js)都可以發(fā)送任意的HTTP請求,可以設(shè)置任何頭字段。 假如我們直接設(shè)置Cookie字段為authed=true并發(fā)送該HTTP請求, 服務(wù)器豈不是被欺騙了?這種攻擊非常容易,Cookie是可以被篡改的!
Cookie 防篡改機(jī)制
服務(wù)器可以為每個Cookie項生成簽名,由于用戶篡改Cookie后無法生成對應(yīng)的簽名, 服務(wù)器便可以得知用戶對Cookie進(jìn)行了篡改。一個簡單的校驗過程可能是這樣的:
通過給Cookie添加簽名,使得服務(wù)器得以知道Cookie被篡改。然而故事并未結(jié)束。
因為Cookie是明文傳輸?shù)?/strong>, 只要服務(wù)器設(shè)置過一次authed=true|xxxx我不就知道true的簽名是xxxx了么, 以后就可以用這個簽名來欺騙服務(wù)器了。因此Cookie中最好不要放敏感數(shù)據(jù)。 一般來講Cookie中只會放一個Session Id,而Session存儲在服務(wù)器端。
Session 的實現(xiàn)機(jī)制
Session 是存儲在服務(wù)器端的,避免了在客戶端Cookie中存儲敏感數(shù)據(jù)。 Session 可以存儲在HTTP服務(wù)器的內(nèi)存中,也可以存在內(nèi)存數(shù)據(jù)庫(如redis)中, 對于重量級的應(yīng)用甚至可以存儲在數(shù)據(jù)庫中。
我們以存儲在redis中的Session為例,還是考察如何驗證用戶登錄狀態(tài)的問題。
如果正確則把當(dāng)前用戶名(通常是用戶對象)存儲到redis中,并生成它在redis中的ID。
這個ID稱為Session ID,通過Session ID可以從Redis中取出對應(yīng)的用戶對象, 敏感數(shù)據(jù)(比如authed=true)都存儲在這個用戶對象中。
Web應(yīng)用框架都會實現(xiàn)上述過程,在Web應(yīng)用中可以直接獲得當(dāng)前用戶。 相當(dāng)于在HTTP協(xié)議之上,通過Cookie實現(xiàn)了持久的會話。這個會話便稱為Session。
轉(zhuǎn)自:?https://harttle.land/2015/08/10/cookie-session.html?
?
?
總結(jié)
以上是生活随笔為你收集整理的Cookie / Session 的机制与安全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qt-重写event(),事件过滤器,定
- 下一篇: nginx 的请求处理、请求的处理流程