一文讓你搞懂cookie

一文讓你搞懂cookie

不知道你是否瞭解 cookie,並且掌握了它的用法。

如果你像我以前一樣,對 cookie 的概念也是略知一二,但是用起來卻一籌莫展,那麼此時此刻你是幸運的。

只要你跟隨者我這篇文章的步伐,就能讓你徹底的搞懂 cookie 了。

接下來,讓我們言歸正傳吧。

什麼是 cookie

首先讓我們引用一段 mdn 上的 cookie 的定義

An HTTP cookie (web cookie, browser cookie) is a small piece of data that a server sends to the user’s web browser. The browser may store it and send it back with the next request to the same server. Typically, it’s used to tell if two requests came from the same browser — keeping a user logged-in, for example. It remembers stateful information for the stateless HTTP protocol.

簡單點說來,cookie 就是服務器發送給客戶端,用來標識訪問的用戶的這麼一個標識,可以理解爲身份令牌吧。

可能這麼說還是不太好理解,那麼我就舉個生活中的小例子來說明吧。

如果把服務器比做銀行,那麼客戶端就可以看作是,到銀行去取錢的人,而 cookie 這個時候,就可以看作是銀行卡。

而銀行卡,當然是有對應的銀行發行的,用來標識客戶的唯一身份的。

cookie 也是這個作用,用來標識請求的頁面的用戶的身份信息用的。

只要用了 cookie,每一次請求數據,都會攜帶這個 cookie,而服務器則會根據這個 cookie 的狀態,判斷,用戶是否有權限執行對應的請求操作。

可以說,有了 cookie 就很方便了,我們不用每次都詢問用戶是誰,因爲 cookie 會告訴我們答案。

而且,一般來說,cookie 也用於簡化用戶的網站使用體驗,比如有了 cookie 信息,客戶端就可以用來判斷,用戶是誰,不用每次重新開啓頁面,都進行登陸操作。

但是有些時候,cookie 也會泄露用戶的隱私,比如網站會用 cookie 來記錄,用戶瀏覽過哪些網頁,這對於有些應用場景下是有必要的,但是在有些場景下,則會給用戶帶來煩惱。

比如有時候,你不小心點開了,網站推薦的商品,結果,後來你每次進來,網站都給你推薦類似的商品。

這就是廣告,當 cookie 遇上廣告,被用作營銷牟利的工具的時候,技術也就變味了。

讓我們先回歸到 cookie 這項技術本身來吧。

cookie 一般不會存在兼容性問題,所有的現代的瀏覽器,都對 cookie 進行了支持。

在前端,我們可以通過 document.cookie 來獲取當前頁面的 cookie,當然更爲友好的方式,是通過瀏覽器的開發者工具來查看當前頁面的 cookie 信息。

截屏2019-12-0600.13.50.png

比如上圖,就是用 Chrome 的 devtools 工具,查看的 cookie 信息。

cookie 可以有多條,而一般一條 cookie 則由 name、value、domain、expires 等等信息組成。

前端操作 cookie

前端最原始的設置 cookie 的方式就是通過 documet.cookie = "test=123;" 然後,再通過 document.cookie 來查看 cookie,便會發現我們設置的測試 cookie 赫然出現在我們的結果之中。

直觀上,這好像與我們的 js 語法相違背!

document.cookie 本身是一個字符串。

怎麼我給 cookie 設置值,他的值不是覆蓋而是拼接到屬性上去了呢。

如果熟悉 es5 的 getter/setter 的同學一定深諳其道,這不就是一個 getter/setter 屬性麼。

而刪除 cookie,則是通過設置 cookie 的過期時間爲現在,就會將對應的 cookie 給刪除掉。

後端使用 cookie

後端使用 cookie,則是通過在請求的回覆中,設置請求頭中的 cookie 的方式來進行設置的。

比如下面,👇,就是在 nodejs 中使用 cookie 的方式:

response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);

這樣設置了以後,就能在 http 的回覆頭中獲取到 cookie 了。

我們看看瀏覽器接收到的 response 的請求頭:

HTTP/1.1 200 OK
Content-Type: text/plain
Set-Cookie: type=ninja
Set-Cookie: language=javascript
Date: Thu, 05 Dec 2019 17:26:28 GMT
Connection: keep-alive
Transfer-Encoding: chunked
X-DNS-Prefetch-Control: off

我們設置了 cookie 以後,默認情況下,以後每次請求的時候,都會自動帶上 cookie。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: max-age=0
Connection: keep-alive
Cookie: type=ninja; language=javascript
DNT: 1
Host: localhost:3002
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36

跨域的處理

以上內容都很好懂,只要自己多揣摩幾次,就會明白其中的緣由。

但是對於跨域的情況下 cookie 的處理,是我們需要掌握的一個重點內容。

跨域代表着不可控,也就是,通過 xhr 請求,來獲取數據,並且客戶端頁面的域名不是服務器的域名。

不跨域,說明頁面是從同一個域名讀取的。

也就是說,在一定程度上,服務器對其內容是可以信賴的,可以放心的提供數據。

所以爲了安全起見,一般瀏覽器都對此做了限制,限制前端直接對後端設置的 cookie 進行修改、讀取等操作,但是當瀏覽器向後端請求的時候,卻能夠自動的攜帶上cookie,用來驗證身份。

所以在這個話題上,我們對於跨域的處理,主要是針對於後端的。

因爲前端,對於跨域的 cookie,確實是無能爲力的。

當然,因爲博主本身是一名前端,最熟悉的後端語言是 nodejs,因此,這個話題,主要針對的是 nodejs 對於前端跨域的處理。

一般情況下,最簡單的,當然是直接允許所有的域名,都能通過。

app.use(
  cors({
    origin: '*',
    credentials: true,
  }),
);

當然,以上代碼是在 express 中的設置方式,如果你用的是別的框架或者原生的,其實原理都差不多。

如果這樣用了,那麼 cookie 是設置不了的。

所以,必須要設置某些域名能夠通過跨域驗證:

app.use(
  cors({
    origin: [
      'http://localhost:3000',
      'http://localhost:3001',
      'http://localhost:8080',
    ],
    credentials: true,
  }),
);

這個域名,不是指服務器的域名,而是指,前端靜態資源所處的服務器的域名。

理解這一點很重要,很多人在這個地方都搞不清楚,或者似懂非懂。

其實 cookie 很簡單,內容並不多,關鍵是要在實戰中,多用,然後才能真正的掌握這個利器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章