HTTP Cookies詳解

HTTP cookies,一般稱之爲「cookie」,已經存在很長時間了,可是仍然沒有被充分理解。首要問題是存在許多誤解,認爲 cookie 是後門程序或病毒,卻忽視了其工做原理。第二個問題是,對於 cookie 的操做缺乏統一的接口。儘管存在這些問題,cookie 仍舊在 Web 開發中扮演者重要的角色,以致於若是沒有出現相應的代替品就消失的話,咱們許多喜歡的 Web 應用將變的不可用。

cookie的起源?編程

早期的 Web 應用面臨的最大問題之一就是如何維持狀態。簡言之,服務器沒法知道兩個請求是否來自於同一個瀏覽器。當時,最簡單的辦法就是在請求的頁面中插入一個 token,而後在下次請求時將這個 token 返回至服務器。這須要在頁面的 form 表單中插入一個包含 token 的隱藏域,或者將 token 放在 URL 的 query 字符串中來傳遞。這兩種方法都須要手動操做,並且極易出錯。瀏覽器

當時網景通信的一名員工 Lou Montulli,在 1994 年將 「magic cookies」 的概念應用到 Web 通信中。他試圖解決 Web 的第一個購物車應用,如今購物車成了購物網站的支柱。他的原始說明文檔提供了 cookie 工做原理的基本信息,該文檔後來被做爲規範歸入到 RFC 2109(大多數瀏覽器的實現參考文檔)中,最終被歸入到 RFC 2965 中。Montulli 也被授予 cookie 的美國專利。網景瀏覽器在它的第一個版本中就開始支持 cookie,如今全部Web瀏覽器都支持 cookie。安全

cookie是什麼?服務器

簡單地說,cookie 就是瀏覽器儲存在用戶電腦上的一小段文本文件。cookie 是純文本格式,不包含任何可執行的代碼。一個 Web 頁面或服務器告知瀏覽器按照必定規範來儲存這些信息,並在隨後的請求中將這些信息發送至服務器,Web 服務器就可使用這些信息來識別不一樣的用戶。大多數須要登陸的網站在用戶驗證成功以後都會設置一個 cookie,只要這個 cookie 存在並能夠,用戶就能夠自由瀏覽這個網站的任意頁面。再次說明,cookie 只包含數據,就其自己而言並不有害。cookie

建立cookie框架

Web服務器經過發送一個稱爲 Set-Cookie 的 HTTP 消息頭來建立一個 cookie,Set-Cookie 消息頭是一個字符串,其格式以下(中括號中的部分是可選的):dom

Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]

消息頭的第一部分,value 部分,一般是一個 name=value 格式的字符串。事實上,這種格式是原始規範中指定的格式,可是瀏覽器並不會對 cookie 值按照此格式來驗證。實際上,你能夠指定一個不含等號的字符串,它一樣會被存儲。然而,最經常使用的使用方式是按照 name=value 格式來指定 cookie 的值(大多數接口只支持該格式)。網站

當存在一個cookie,並容許設置可選項,該 cookie 的值會在隨後的每次請求中被髮送至服務器,cookie 的值被存儲在名爲 Cookie 的 HTTP 消息頭中,而且只包含了 cookie 的值,忽略所有設置選項。例如:google

Cookie: value

經過 Set-Cookie 指定的可選項只會在瀏覽器端使用,而不會被髮送至服務器端。發送至服務器的 cookie 的值與經過 Set-Cookie 指定的值徹底同樣,不會有進一步的解析或轉碼操做。若是請求中包含多個 cookie,它們將會被分號和空格分開,例如:編碼

Cookie: value1; value2; name1=value1

服務器端框架一般包含解析 cookie 的方法,能夠經過編程的方式獲取 cookie 的值。

cookie編碼

對於 cookie 的值進行編碼一直都存在一些困惑。廣泛認爲 cookie 的值必須通過 URL 編碼,但其實這是一個謬論,儘管一般都這麼作。原始規範中明確指出只有三個字符必須進行編碼:分號、逗號和空格,規範中還提到能夠進行 URL 編碼,但並非必須,在 RFC 中沒有說起任何編碼。然而,幾乎全部的實現都對 cookie 的值進行了一系列的 URL 編碼。對於 name=value 格式,一般會對 name 和 value 分別進行編碼,而不對等號 = 進行編碼操做。

cookie過時時間選項

緊跟cookie值後面的每一個選項都以分號和空格分開,每一個選擇都指定了 cookie 在什麼狀況下應該被髮送至服務器。第一個選項是過時時間(expires),指定了 cookie 什麼時候不會再被髮送至服務器,隨後瀏覽器將刪除該 cookie。該選項的值是一個 Wdy, DD-Mon-YYYY HH:MM:SS GMT 日期格式的值,例如:

Set-Cookie: name=Nicholas; expires=Sat, 02 May 2009 23:38:25 GMT

沒有設置 expires 選項時,cookie 的生命週期僅限於當前會話中,關閉瀏覽器意味着此次會話的結束,因此會話 cookie 僅存在於瀏覽器打開狀態之下。這就是爲何爲何當你登陸一個 Web 應用時常常會看到一個複選框,詢問你是否記住登陸信息:若是你勾選了複選框,那麼一個 expires 選項會被附加到登陸 cookie 中。若是 expires 設置了一個過去的時間點,那麼這個 cookie 會被當即刪掉。

cookie的屬性

domain選項

下一個選項是 domain,指定了 cookie 將要被髮送至哪一個或哪些域中。默認狀況下,domain 會被設置爲建立該 cookie 的頁面所在的域名,因此當給相同域名發送請求時該 cookie 會被髮送至服務器。例如,本博中 cookie 的默認值將是 bubkoo.com。domain 選項可用來擴充 cookie 可發送域的數量,例如:

Set-Cookie: name=Nicholas; domain=nczonline.net

像 Yahoo! 這種大型網站,都會有許多 name.yahoo.com 形式的站點(例如:my.yahoo.com, finance.yahoo.com 等等)。將一個 cookie 的 domain 選項設置爲 yahoo.com,就能夠將該 cookie 的值發送至全部這些站點。瀏覽器會把 domain 的值與請求的域名作一個尾部比較(即從字符串的尾部開始比較),並將匹配的 cookie 發送至服務器。domain選項的值必須是發送 Set-Cookie 消息頭的主機名的一部分,例如我不能在 google.com 上設置一個 cookie,由於這會產生安全問題。不合法的 domain 選擇將直接被忽略。

path選項

另外一個控制 Cookie 消息頭髮送時機的選項是 path 選項,和 domain 選項相似,path 選項指定了請求的資源 URL 中必須存在指定的路徑時,纔會發送Cookie 消息頭。這個比較一般是將 path 選項的值與請求的 URL 從頭開始逐字符比較完成的。若是字符匹配,則發送 Cookie 消息頭,例如:

Set-Cookie:name=Nicholas;path=/blog

在這個例子中,path 選項值會與 /blog,/blogrool 等等相匹配;任何以 /blog 開頭的選項都是合法的。須要注意的是,只有在 domain 選項覈實完畢以後纔會對 path 屬性進行比較。path 屬性的默認值是發送 Set-Cookie 消息頭所對應的 URL 中的 path 部分。

secure選項

最後一個選項是 secure。不像其它選項,該選項只是一個標記而沒有值。只有當一個請求經過 SSL 或 HTTPS 建立時,包含 secure 選項的 cookie 才能被髮送至服務器。這種 cookie 的內容具備很高的價值,若是以純文本形式傳遞頗有可能被篡改,例如:

Set-Cookie: name=Nicholas; secure

事實上,機密且敏感的信息毫不應該在 cookie 中存儲或傳輸,由於 cookie 的整個機制本來都是不安全的。默認狀況下,在 HTTPS 連接上傳輸的 cookie 都會被自動添加上 secure 選項。

cookie使用失效日期

當 cookie 建立時指定了失效日期,這個失效日期則關聯了以 name-domain-path-secure 爲標識的 cookie。要改變一個 cookie 的失效日期,你必須指定一樣的組合。當改變一個 cookie 的值時,你沒必要每次都設置失效日期,由於它不是 cookie 標識信息的組成部分。例如:

Set-Cookie:name=Mike;expires=Sat,03 May 2025 17:44:22 GMT

如今已經設置了 cookie 的失效日期,因此下次我想要改變 cookie 的值時,我只須要使用它的名字:

Set-Cookie:name=Matt

cookie 的失效日期並無改變,由於 cookie 的標識符是相同的。實際上,只有你手工的改變 cookie 的失效日期,不然其失效日期不會改變。這意味着在同一個會話中,一個會話 cookie 能夠變成一個持久化 cookie(一個能夠在多個會話中存在的),反之則不可。爲了要將一個持久化 cookie 變爲一個會話 cookie,你必須刪除這個持久化 cookie,這隻要設置它的失效日期爲過去某個時間以後再建立一個同名的會話 cookie 就能夠實現。

須要記得的是失效日期是以瀏覽器運行的電腦上的系統時間爲基準進行覈實的。沒有任何辦法來來驗證這個系統時間是否和服務器的時間同步,因此當服務器時間和瀏覽器所處系統時間存在差別時這樣的設置會出現錯誤。

cookie自動刪除

cookie 會被瀏覽器自動刪除,一般存在如下幾種緣由:

1)會話 cooke (Session cookie) 在會話結束時(瀏覽器關閉)會被刪除。

2)持久化 cookie(Persistent cookie)在到達失效日期時會被刪除。

3)若是瀏覽器中的 cookie 數量達到限制,那麼 cookie 會被刪除覺得新建的 cookie 建立空間。詳見個人另一篇關於 cookies restrictions 的博客。

對於自動刪除來講,Cookie 管理顯得十分重要,由於這些刪除都是無心識的。

總結

爲了高效的利用 cookie,仍舊有許多要了解和弄明白的東西。對於一項建立於十多年前但仍舊如最初實現的那樣被使用至今的技術來講,這是件多難以想象的事。本篇只是提供了一些每一個人都應該知道的關於瀏覽器 cookie 的基本指導,但不管如何,也不是一個完整的參考。對於今天的 Web 來講 cookie 仍舊起着很是重要的做用,而且不恰當的管理 cookie 會致使各類各樣的問題,從最糟糕的用戶體驗到安全漏洞。我但願這篇手冊可以激起一些關於 cookie 的難以想象的亮點。

相關文章
相關標籤/搜索