由於某次開發中遇到了cookie的坑,因此決心認真看cookie的機制,首選RFC。原文連接 rfc HTTP State Management Mechanism 1997 有點老其實。ajax
**申明:盡力翻譯,非徹底翻譯,有誤的歡迎指正哈**
這篇文檔是爲HTTP request 和 response之間建立一個有狀態的會話指明一個方法,並描述了兩個頭字段:Cookie和Set-cookie,用於攜帶服務端和客戶端之間的狀態信息。算法
FQHN(fully-qualified host name):指的是主機的FQDN(fully-qualified domain name),好比以1級域名.com 或 .uk結尾的徹底指定的域名,或者指主機的IP地址。(傾向於前者,後者不建議)
request-host:指的是客戶端發出請求指向的服務器端的主機(跟端口無關),這裏request-host是一個FQHN.
request-URI:指的是客戶端發出請求指向的服務器端絕對路徑部分。
host-name:指的是一個IP地址或者一個FQHN字符串。
domain-match:知足下面其中一種狀況則A的host-name domain-match B的host-name:segmentfault
二者的host-name都是IP並徹底一致瀏覽器
二者的host-name都是FQDN字符串且徹底一致緩存
A的host-name是FQDN字符串而且格式爲NB,其中N是一個非空字符串,B個格式是.C,而C是一個FQDN字符串。也就是說A = N.C,B = .C的狀況。好比:域x.y.com就domain-match 域.y.com,而域x.y.com就不domain-match 域y.com。(這個定義對是否能使用某個域的cookie很是關鍵)同時要注意,A domain-match B,不能說明B domain-math A,一樣須要經過這個定義來判斷。安全
Set-cookie 和 Cookie這兩個頭字段有類似的語法。
(Set-cookie/Cookie) = av-pair *(";" av-pair)
其中:
av-pair = attr ["=" value]
attr = token
value = word
word = token | quoted-string(帶引號的字符串)
這裏邊,token的定義得去查看HTTP/1.1 specification [RFC 2068] 。等號左右容許有空格。服務器
爲了與客戶端之間的會話保持狀態信息,服務器端在response頭中使用Set-Cookie字段,而客戶端若是想保持狀態信息,得在request頭中加Cookie字段。服務器端若要終止這個會話,能夠簡單的設置Set-Cookie爲Max-Age=0。
服務器端可能會包含多個Set-cookie字段,不過網關會把這些合併成一個Set-cookie字段,用逗號,分隔。cookie
Set-Cookiedom
set-cookie = "Set-Cookie:" cookies
其中
cookies = 1#cookie
cookie = NAME "=" VALUE *(";" cookie-av)
NAME = attr
VALUE = value
cookie-av = "Comment" "=" value | "Domain" "=" value | "Max-Age" "=" value | "Path" "=" value | "Secure" | "Version" "=" 1*DIGITui
NAME=VALUE:必須的,雖然VALUE嚴格上來講對客戶端是不透明的,然實際上經過檢查Set-Cookie字段仍是能夠讀到的。
Comment=comment:可選,描述該Cookie的用處。
Domain=domain:可選,指定了cookie有效的域。明確指定的domain必須以.開頭。
Max-Age=delta-seconds:可選,指cookie的存活時間,以秒爲單位,非負數。Max-Age=0表示客戶端須要當即丟棄該cookie。
Path=path:可選,指在某URL的子路徑下cookie有效。
Secure:可選,(翻者注:有點難理解)查閱資料解釋以下:建立的 Cookie 會被以安全的形式向服務器傳輸,也就是隻能在 HTTPS 鏈接中被瀏覽器傳遞到服務器端進行會話驗證,若是是 HTTP 鏈接則不會傳遞該信息,因此不會被竊取到Cookie 的具體內容。
HTTP狀態管理機制 2011 補充
HttpOnly:可選,用於告訴客戶端不能經過」non-HTTP「的方式獲取cookie(好比瀏覽器的API:document.cookie)。
Version=version:必須。十進制的整數,指狀態管理中cookie指向的版本。
控制緩存
若是cookie只給某一用戶使用,則Set-Cookie頭不能被緩存,相反則應該緩存。
根據狀況,服務器端應該在response頭中添加一些字段:
禁止緩存Set-Cookie頭,則:Cache-control:no-cache="set-cookie"。
禁止在共享緩存中緩存私密文檔:Cache-control:private。
To allow caching of a document, but to require that proxy caches (not user agent caches) validate it before returning it to the client:Cache-control:proxy-revalidata。(譯者注:這條跟下面一條區別在哪裏沒看出)
To allow caching of a document and request that it be validated before returning it to the client (by "pre-expiring" it): Cache-control:max-age=0
HTTP/1.1服務器若是不肯定下游是否有代理,則必須設置Expires: old-date。(譯者注:防止cookie被代理緩存,會產生bug)。Cache-Control指令會覆蓋Expires:old-date。
客戶端在接收到Set-Cookie的response頭以後,會對其中可選的屬性應用默認值:
Version:根據Netscape規範。
Domain:默認爲request-host(不是以.開頭)(譯者注:服務器端有時候會不設置這個Domain,覺得到了客戶端以後會設置成客戶端的域名,實際上是目標服務器的域名)。
Max-Age:默認行爲是若是客戶端存在這個cookie,那這個cookie會被清除掉。
Path:請求URL中的path,不右邊最右邊的'/'。
Secure:客戶端將經過一條不安全的通道發送cookie(譯者注:也就是Http)。
拒絕cookie
考慮安全,若是知足下面的狀況,客戶端將不會保存cookie:
Path不是request-URI的前綴。
Domain的值不是以.開頭或者沒有內含的點(eg: .com沒有,segmentfault.com有)。
request-host不 domain-match Domain的值。
request-host是個FQDN而且格式爲HD,其中D是Domain的值,H是一個包含.的字符串。
舉例子:
request-host = x.foo.com,Domain = .foo.com 經過。
Domain=.com 或者 Domain=.com. 不經過,由於沒有內含的點.。
Domain=ajax.com 不經過,由於沒有以.開頭。
Cookie 管理
若是Set-Cookie中的cookie名字已經存在在客戶端裏,而且Domain和Path都同樣,那麼新的Cookie會覆蓋舊的;若是新的Cookie中Max-Age=0,那麼新舊cookie都會被清除掉。
因爲客戶端存儲cookie的空間有限,因此可能會應用如LRU等算法來清除舊的cookie。
發送Cookie到服務器端
基於下面幾種,客戶端會在發送請求到服務器端的時候將cookie包含在request頭中。
request-host
request-URI
cookie的存活時間
Cookie頭的語法:
cookie = "Cookie:" cookie-version 1*((","|";") cookie-value)
其中:
cookie-value = NAME "=" VALUE";" path
cookie-version = "$Version" "=" value
NAME = attr
VALUE = value
path = "$Path" "=" value
domain = "$Domain" "=" value
同時以上屬性的值有這樣的要求:若是有相應的Set-Cookie response頭,則cookie-version的值應該與此response中的cookie-version一致,不然爲0.同理path也需一致,不然該屬性會被剔除掉。同理Domain的值也需一致,不然也會被剔除掉。
請求頭中能夠包含哪些cookie有如下規則:
Domain:服務器端的FQHN必須domain-match Domain的值。
Path:Path的值必須是request-URI的前綴。
Max-Age:不能是已通過期了。
緩存代理服務器必須遵循下面規範:
依據緩存驗證規則。
將response頭(包含Set-cookie)傳遞到客戶端。
將request頭(包含Cookie)傳遞給服務器端。