天天看點

一個請求裡能有多個cookie嗎_HTTP之Cookie機制

Cookie 的工作過程

當使用者通過浏覽器第一次通路伺服器的時候,伺服器肯定是不知道他的身份的。是以,就要建立一個獨特的身份辨別資料,格式是“key=value”,然後放進 Set-Cookie 字段裡,随着響應封包一同發給浏覽器。

浏覽器收到響應封包,看到裡面有 Set-Cookie,知道這是伺服器給的身份辨別,于是就儲存起來,下次再請求的時候就自動把這個值放進 Cookie 字段裡發給伺服器。

因為第二次請求裡面有了 Cookie 字段,伺服器就知道這個使用者不是新人,之前來過,就可以拿出 Cookie 裡的值,識别出使用者的身份,然後提供個性化的服務。

不過因為伺服器的“記憶能力”實在是太差,一張小紙條經常不夠用。是以,伺服器有時會在響應頭裡添加多個 Set-Cookie,存儲多個“key=value”。但浏覽器這邊發送時不需要用多個 Cookie 字段,隻要在一行裡用“;”隔開就行

一個請求裡能有多個cookie嗎_HTTP之Cookie機制

從這張圖中我們也能夠看到,

Cookie

 是由浏覽器負責存儲的,而不是作業系統。是以,它是“浏覽器綁定”的,隻能在本浏覽器内生效。

如果你換個浏覽器或者換台電腦,新的浏覽器裡沒有伺服器對應的 

Cookie

,就好像是脫掉了貼着紙條的衣服,“健忘”的伺服器也就認不出來了,隻能再走一遍 

Set-Cookie

 流程

Cookie 的屬性

說到這裡,你應該知道了,Cookie 就是伺服器委托浏覽器存儲在用戶端裡的一些資料,而這些資料通常都會記錄使用者的關鍵識别資訊。是以,就需要在“key=value”外再用一些手段來保護,防止外洩或竊取,這些手段就是 Cookie 的屬性。

一個請求裡能有多個cookie嗎_HTTP之Cookie機制

首先,我們應該設定 

Cookie

 的生存周期,也就是它的有效期,讓它隻能在一段時間内可用,就像是食品的“保鮮期”,一旦超過這個期限浏覽器就認為是 

Cookie

 失效,在存儲裡删除,也不會發送給伺服器。

Cookie 的有效期可以使用 Expires 和 Max-Age 兩個屬性來設定。

“Expires”俗稱“過期時間”,用的是絕對時間點,可以了解為“截止日期”(deadline)。“Max-Age”用的是相對時間,機關是秒,浏覽器用收到封包的時間點再加上 Max-Age,就可以得到失效的絕對時間。

Expires 和 Max-Age 可以同時出現,兩者的失效時間可以一緻,也可以不一緻,但浏覽器會優先采用 Max-Age 計算失效期。

比如在這個例子裡,Expires 标記的過期時間是“GMT 2019 年 6 月 7 号 8 點 19 分”,而 Max-Age 則隻有 10 秒,如果現在是 6 月 6 号零點,那麼 Cookie 的實際有效期就是“6 月 6 号零點過 10 秒”。

其次,我們需要設定 Cookie 的作用域,讓浏覽器僅發送給特定的伺服器和 URI,避免被其他網站盜用。

作用域的設定比較簡單,“Domain”和“Path”指定了 Cookie 所屬的域名和路徑,浏覽器在發送 Cookie 前會從 URI 中提取出 host 和 path 部分,對比 Cookie 的屬性。如果不滿足條件,就不會在請求頭裡發送 Cookie。

使用這兩個屬性可以為不同的域名和路徑分别設定各自的 Cookie,比如“/19-1”用一個 Cookie,“/19-2”再用另外一個 Cookie,兩者互不幹擾。不過現實中為了省事,通常 Path 就用一個“/”或者直接省略,表示域名下的任意路徑都允許使用 Cookie,讓伺服器自己去挑。

最後要考慮的就是Cookie 的安全性了,盡量不要讓伺服器以外的人看到。

寫過前端的同學一定知道,在 JS 腳本裡可以用 document.cookie 來讀寫 Cookie 資料,這就帶來了安全隐患,有可能會導緻“跨站腳本”(XSS)攻擊竊取資料。

屬性“HttpOnly”會告訴浏覽器,此 Cookie 隻能通過浏覽器 HTTP 協定傳輸,禁止其他方式通路,浏覽器的 JS 引擎就會禁用 document.cookie 等一切相關的 API,腳本攻擊也就無從談起了。

另一個屬性“SameSite”可以防範“跨站請求僞造”(XSRF)攻擊,設定成“SameSite=Strict”可以嚴格限定 Cookie 不能随着跳轉連結跨站發送,而“SameSite=Lax”則略寬松一點,允許 GET/HEAD 等安全方法,但禁止 POST 跨站發送。

還有一個屬性叫“Secure”,表示這個 Cookie 僅能用 HTTPS 協定加密傳輸,明文的 HTTP 協定會禁止發送。但 Cookie 本身不是加密的,浏覽器裡還是以明文的形式存在。

Chrome 開發者工具是檢視 Cookie 的有力工具,在“Network-Cookies”裡可以看到單個頁面 Cookie 的各種屬性,另一個“Application”面闆裡則能夠友善地看到全站的所有 Cookie

Cookie 的應用

現在回到我們最開始的話題,有了 Cookie,伺服器就有了“記憶能力”,能夠儲存“狀态”,那麼應該如何使用 Cookie 呢?

Cookie 最基本的一個用途就是身份識别,儲存使用者的登入資訊,實作會話事務。

比如,你用賬号和密碼登入某電商,登入成功後網站伺服器就會發給浏覽器一個 Cookie,内容大概是“name=yourid”,這樣就成功地把身份标簽貼在了你身上。

之後你在網站裡随便通路哪件商品的頁面,浏覽器都會自動把身份 Cookie 發給伺服器,是以伺服器總會知道你的身份,一方面免去了重複登入的麻煩,另一方面也能夠自動記錄你的浏覽記錄和購物下單(在背景資料庫或者也用 Cookie),實作了“狀态保持”。

Cookie 的另一個常見用途是廣告跟蹤。

你上網的時候肯定看過很多的廣告圖檔,這些圖檔背後都是廣告商網站(例如 Google),它會“偷偷地”給你貼上 Cookie 小紙條,這樣你上其他的網站,别的廣告就能用 Cookie 讀出你的身份,然後做行為分析,再推給你廣告。

這種 Cookie 不是由通路的主站存儲的,是以又叫“第三方 Cookie”(third-party cookie)。如果廣告商勢力很大,廣告到處都是,那麼就比較“恐怖”了,無論你走到哪裡它都會通過 Cookie 認出你來,實作廣告“精準打擊”。

為了防止濫用 Cookie 搜集使用者隐私,網際網路組織相繼提出了 DNT(Do Not Track)和 P3P(Platform for Privacy Preferences Project),但實際作用不大

小結

  • Cookie

     是伺服器委托浏覽器存儲的一些資料,讓伺服器有了“記憶能力”;
  • 響應封包使用 

    Set-Cookie

     字段發送“

    key=value

    ”形式的 

    Cookie

     值;
  • 請求封包裡用 

    Cookie

     字段發送多個 

    Cookie

     值;
  • 為了保護 

    Cookie

    ,還要給它設定有效期、作用域等屬性,常用的有 

    Max-Age

    Expires

    Domain

    HttpOnly

     等;
  • Cookie

     最基本的用途是身份識别,實作有狀态的會話事務