App下載

cookie的介紹和使用

猿友 2021-02-22 14:01:19 瀏覽數(shù) (9504)
反饋

一、概述

Cookie 是服務(wù)器保存在瀏覽器的一小段文本信息,一般大小不能超過4KB。瀏覽器每次向服務(wù)器發(fā)出請(qǐng)求,就會(huì)自動(dòng)附上這段信息。

Cookie 主要保存狀態(tài)信息,以下是一些主要用途。

  • 對(duì)話(session)管理:保存登錄、購物車等需要記錄的信息。
  • 個(gè)性化信息:保存用戶的偏好,比如網(wǎng)頁的字體大小、背景色等等。
  • 追蹤用戶:記錄和分析用戶行為。

Cookie 不是一種理想的客戶端儲(chǔ)存機(jī)制。它的容量很?。?KB),缺乏數(shù)據(jù)操作接口,而且會(huì)影響性能??蛻舳藘?chǔ)存應(yīng)該使用 Web storage API 和 IndexedDB。只有那些每次請(qǐng)求都需要讓服務(wù)器知道的信息,才應(yīng)該放在 Cookie 里面。

有關(guān)對(duì)Web storage的介紹,可以看這篇博客:sessionStorage 和 localStorage 的使用

每個(gè) Cookie 都有以下幾方面的元數(shù)據(jù)。

  • Cookie 的名字
  • Cookie 的值(真正的數(shù)據(jù)寫在這里面)
  • 到期時(shí)間(超過這個(gè)時(shí)間會(huì)失效)
  • 所屬域名(默認(rèn)為當(dāng)前域名)
  • 生效的路徑(默認(rèn)為當(dāng)前網(wǎng)址)

舉例來說,用戶訪問網(wǎng)址 ?www.example.com?,服務(wù)器在瀏覽器寫入一個(gè) Cookie。這個(gè) Cookie 的所屬域名為 ?www.example.com?,生效路徑為根路徑 ?/?。

如果 Cookie 的生效路徑設(shè)為? /user?,那么這個(gè) Cookie 只有在訪問? www.example.com/use?r 及其子路徑時(shí)才有效。以后,瀏覽器訪問某個(gè)路徑之前,就會(huì)找出對(duì)該域名和路徑有效,并且還沒有到期的 Cookie,一起發(fā)送給服務(wù)器。

用戶可以設(shè)置瀏覽器不接受 Cookie,也可以設(shè)置不向服務(wù)器發(fā)送 Cookie。 window.navigator.cookieEnabled 屬性返回一個(gè)布爾值,表示瀏覽器是否打開 Cookie 功能。

window.navigator.cookieEnabled // true

?document.cookie? 屬性返回當(dāng)前網(wǎng)頁的 Cookie。

不同瀏覽器對(duì) Cookie 數(shù)量和大小的限制,是不一樣的。一般來說,單個(gè)域名設(shè)置的 Cookie 不應(yīng)超過30個(gè),每個(gè) Cookie 的大小不能超過4KB。超過限制以后,Cookie 將被忽略,不會(huì)被設(shè)置。

兩個(gè)網(wǎng)址只要域名相同,就可以共享 Cookie。 注意,這里不要求協(xié)議相同。也就是說,?http://example.com ?設(shè)置的 Cookie,可以被 ?https://example.com? 讀取。

二、Cookie 與 HTTP 協(xié)議

Cookie 由 HTTP 協(xié)議生成,也主要是供 HTTP 協(xié)議使用。

1、HTTP 回應(yīng):Cookie 的生成

服務(wù)器如果希望在瀏覽器保存 Cookie,就要在 HTTP 回應(yīng)的頭信息里面,放置一個(gè) ?Set-Cookie? 字段。

Set-Cookie:foo=bar

上面代碼會(huì)在瀏覽器保存一個(gè)名為 foo 的 Cookie,它的值為 bar。

HTTP 回應(yīng)可以包含多個(gè) ?Set-Cookie? 字段,即在瀏覽器生成多個(gè) Cookie。

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

除了 Cookie 的值,Set-Cookie字段還可以附加 Cookie 的屬性。一個(gè)Set-Cookie字段里面,可以同時(shí)包括多個(gè)屬性,沒有次序的要求。

Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly

在這里插入圖片描述

2、HTTP 請(qǐng)求:Cookie 的發(fā)送

瀏覽器向服務(wù)器發(fā)送 HTTP 請(qǐng)求時(shí),每個(gè)請(qǐng)求都會(huì)帶上相應(yīng)的 Cookie。也就是說,把服務(wù)器早前保存在瀏覽器的這段信息,再發(fā)回服務(wù)器。這時(shí)要使用 HTTP 頭信息的 ?Cookie? 字段。

// 會(huì)向服務(wù)器發(fā)送名為 foo的 Cookie,值為 bar。
Cookie: foo=bar

// Cookie字段可以包含多個(gè) Cookie,使用分號(hào)(;)分隔。
Cookie: name=value; name2=value2; name3=value3

下面是一個(gè)例子。

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

在這里插入圖片描述

三、Cookie 的屬性

1、Expires,Max-Age

?Expires? 屬性指定一個(gè)具體的到期時(shí)間,到了指定時(shí)間以后,瀏覽器就不再保留這個(gè) Cookie。它的值是 UTC 格式,可以使用?Date.prototype.toUTCString()? 進(jìn)行格式轉(zhuǎn)換。

如果不設(shè)置該屬性,或者設(shè)為null,Cookie 只在當(dāng)前會(huì)話(session)有效,瀏覽器窗口一旦關(guān)閉,當(dāng)前會(huì)話結(jié)束,該 Cookie 就會(huì)被刪除。另外,瀏覽器根據(jù)本地時(shí)間,決定 Cookie 是否過期,由于本地時(shí)間是不精確的,所以沒有辦法保證 Cookie 一定會(huì)在服務(wù)器指定的時(shí)間過期。

?Max-Age屬性指定從現(xiàn)在開始 Cookie 存在的秒數(shù),比如 60 * 60 * 24 * 365(即一年)。過了這個(gè)時(shí)間以后,瀏覽器就不再保留這個(gè) Cookie。

如果同時(shí)指定了 ?Expires? 和 ?Max-Age?,那么? Max-Age? 的值將優(yōu)先生效。

如果 ?Set-Cookie? 字段沒有指定?Expires?或?Max-Age?屬性,那么這個(gè) Cookie 就是 Session Cookie,即它只在本次對(duì)話存在,一旦用戶關(guān)閉瀏覽器,瀏覽器就不會(huì)再保留這個(gè) Cookie。

使用 Node 創(chuàng)建一個(gè)服務(wù)器來模擬演示:

const http = require('http')
const fs = require('fs')

http.createServer(function (request, response) {
  console.log('request come', request.url)
  
  const html = fs.readFileSync('test.html', 'utf8')
  response.writeHead(200, {
    'Content-Type': 'text/html',
    'Set-Cookie': ['id=123;max-age=2', 'abc=456;HttpOnly']
  })
  response.end(html)

}).listen(8888)

console.log('http://127.0.0.1:8888')

在這里插入圖片描述

在這里插入圖片描述

2、Domain,Path

?Domain?屬性指定瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),哪些域名要附帶這個(gè) Cookie。

  • 如果沒有指定該屬性,瀏覽器會(huì)默認(rèn)將其設(shè)為當(dāng)前域名,這時(shí)子域名將不會(huì)附帶這個(gè) Cookie。比如,?example.com? 不設(shè)置 Cookie 的domain屬性,那么 sub.example.com 將不會(huì)附帶這個(gè) Cookie。
  • 如果指定了domain屬性,那么子域名也會(huì)附帶這個(gè) Cookie。如果服務(wù)器指定的域名不屬于當(dāng)前域名,瀏覽器會(huì)拒絕這個(gè) Cookie。
  • 一句話總結(jié):Domain標(biāo)識(shí)指定了哪些主機(jī)可以接受Cookie。如果不指定,默認(rèn)為當(dāng)前主機(jī)(不包含子域名)。如果指定了Domain ,則一般包含子域名。

?Path?屬性指定瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),哪些路徑要附帶這個(gè) Cookie。只要瀏覽器發(fā)現(xiàn),Path屬性是 HTTP 請(qǐng)求路徑的開頭一部分,就會(huì)在頭信息里面帶上這個(gè) Cookie。比如,PATH屬性是 ?/?,那么請(qǐng)求 ?/docs ?路徑也會(huì)包含該 Cookie。當(dāng)然,前提是域名必須一致。

3、Secure,HttpOnly

?Secure ?屬性指定瀏覽器只有在加密協(xié)議 HTTPS 下,才能將這個(gè) Cookie 發(fā)送到服務(wù)器。另一方面,如果當(dāng)前協(xié)議是 HTTP,瀏覽器會(huì)自動(dòng)忽略服務(wù)器發(fā)來的Secure屬性。該屬性只是一個(gè)開關(guān),不需要指定值。如果通信是 HTTPS 協(xié)議,該開關(guān)自動(dòng)打開。

?HttpOnly? 屬性指定該 Cookie 無法通過 JavaScript 腳本拿到,主要是 ?document.cookie? 屬性、?XMLHttpRequest? 對(duì)象和 ?Request API? 都拿不到該屬性。這樣就防止了該 Cookie 被腳本讀到,只有瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),才會(huì)帶上該 Cookie。出于安全考慮。

四、document.cookie

?document.cookie? 屬性用于讀寫當(dāng)前網(wǎng)頁的 Cookie。讀取的時(shí)候,它會(huì)返回當(dāng)前網(wǎng)頁的所有 Cookie,前提是該 Cookie 不能有HTTPOnly屬性。

document.cookie // "foo=bar;baz=bar"

上面代碼從? document.cookie ?一次性讀出兩個(gè) Cookie,它們之間使用分號(hào)分隔。必須手動(dòng)還原,才能取出每一個(gè) Cookie 的值。這就是cookie存取數(shù)據(jù)不方便的地方,它沒有完善的存取數(shù)據(jù)的api讓我們用,我們必須手動(dòng)的從中提取自己需要的數(shù)據(jù)。

?document.cookie? 屬性是可寫的,可以通過它為當(dāng)前網(wǎng)站添加 Cookie。寫入的時(shí)候,Cookie 的值必須寫成?key=value?的形式。注意,等號(hào)兩邊不能有空格。? document.cookie?一次只能寫入一個(gè) Cookie,而且寫入并不是覆蓋,而是添加。

document.cookie = 'fontSize=14';

// 最終只會(huì)有 test1=456 被寫進(jìn)去
document.cookie = 'test1=456;hahah=123'

?document.cookie ?讀寫行為的差異(一次可以讀出全部 Cookie,但是只能寫入一個(gè) Cookie),與 HTTP 協(xié)議的 Cookie 通信格式有關(guān)。

  • 瀏覽器向服務(wù)器發(fā)送 Cookie 的時(shí)候,Cookie字段是使用一行將所有 Cookie 全部發(fā)送;
  • 服務(wù)器向?yàn)g覽器設(shè)置 Cookie 的時(shí)候,?Set-Cookie?字段是一行設(shè)置一個(gè) Cookie。

刪除一個(gè)現(xiàn)存 Cookie 的唯一方法,是設(shè)置它的? expires? 屬性為一個(gè)過去的日期。

document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';

五、參考資料

HTTP cookies 詳解


0 人點(diǎn)贊