Cookie和Session在Node.JS中的實踐(一) Cookie和Session是一個非常有趣的概念,也是一個老生常談的話題。然而,作者看了許多文章,也翻看了幾本書籍,它們對Cookie和Session的概念、機制的描述都各不一致,大多文章都只談到了Cookie和Session其中之一,但在 ...
Cookie和Session在Node.JS中的實踐(一)
Cookie和Session是一個非常有趣的概念,也是一個老生常談的話題。然而,作者看了許多文章,也翻看了幾本書籍,它們對Cookie和Session的概念、機制的描述都各不一致,大多文章都只談到了Cookie和Session其中之一,但在現實開發中兩者都需要使用。作者有時候寫程式用到了兩者但有時候連自己都沒理解他們之間的區別、聯繫、機制等等概念。
Cookie
HTTP的無狀態協議是產生Cookie技術的重要原因
HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議自身不對請求和響應之間的通信轉檯進行保存。也就是說HTTP是不會做持久化(Persistence)處理的。當使用HTTP進行通信時,每當有新的請求發送,就會有對應的新響應產生。這並不是缺陷,而是HTTP為了更快的處理大量事務。
然而,無狀態協議讓業務處理變得困難的情況越來越多了,如:我們登錄了某寶,就算我們跳轉到了某寶的其他頁面,也需要保持登錄這個“狀態”,但HTTP協議做不到。針對這個例子,網站為了掌握是誰發送的請求,就需要把用戶的狀態保存起來。
為了實現期望的保持狀態功能,於是引入了Cookie技術,所以cookie的主要作用就是記錄狀態,包括會話狀態管理,用戶的個性化設置,瀏覽器的行為跟蹤。有了Cookie再用HTTP通信就可以管理狀態,因此就有人說Cookie是HTTP的擴展。
客戶端中的Cookie
Cookie是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶併發送到伺服器上。
這是我們經常聽到的關於Cookie的概念,但從來沒見過Cookie長什麼樣子。在Chrome中通過開發者工具可以查看網站用到的所有Cookie,以博客園用到的Cookie為例。
另外我們可以使用JavaScript
原生的API獲取cookie:document.cookie
,使用該方法獲只能獲取非HttpOnly
類型的cookie。
跟直接在chrome
查看cookie
,使用控制台Console得到的結果除了HttpOnly
以外的Cookie都是一樣的。可以發現,每一個cookie
都有幾個不同的欄位:name,value,domain,path,expires/max-age,HttpOnly,secure
來分析一下比較常用的欄位:
name和value
設置cookie
的名字和值。必須設置欄位。
domain和path
domain
是功能變數名稱,path
是路徑,兩者加起來就是URL,domain
結合path
一起來限制cookie能被哪些URL訪問。概念比較抽象,舉個例子
以博客園為例,博客園cookie的
domain
為"cnblogs.com",path
為"/",若我們請求的URL的功能變數名稱是"cnblogs.com"或者它的子域"home.cnblogs.com",並且URL的路徑都是"/"或者它的子路徑"/example","/home/user",以上這些URL都能訪問cookie,瀏覽器會將這些cookie添加到請求的cookie頭部中去。
以上兩個欄位是可選的,domain
預設cookie所在的功能變數名稱,path
預設設置該cookie的網頁所在的目錄。
secure
帶有此欄位的cookie表示只有在請求使用HTTPS協議的時候才能被傳到伺服器中。但通常建議不會把保密的數據放到cookie中存儲。
HttpOnly
JavaScript原生API能訪問瀏覽器的cookie,這可能會遭遇XSS
攻擊,為了防範,設置了該欄位的cookie,原生API是無法訪問的。
expire和Max-age
expires
:表示cookie的最長有效時間,cookie失效時刻=expires形式是符合HTTP-date
規範的時間戳,這個Date
是一個通用的首部,語法:Date: <day-name> <day> <month> <year> <hour>:<minute>:<second> GMT
,可以通過new Date().toGMTString獲得
。
Max-Age
:表示cookie存儲的最長時間。單位是秒,有效期:創建時刻+max-age
。跟expire的作用的一樣的,若兩者都存在則Max-Age
的優先順序高。該屬性在一些老瀏覽器中不支持。
如果沒有給cookie設置以上這兩個欄位,那麼cookie預設就是所謂的會話Cookie
,有效期就是session
,這裡的session指的就是會話,瀏覽器關閉後cookie就沒有了整個過程就是一個會話。
HTTP+COOKIE工作原理
HTTP是無狀態協議,所以需要COOKIE技術來保持狀態。我們知道,Cookie是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,這裡分析一下HTTP+COOKIE的工作原理:
考慮兩種可能:
1.客戶端第一請求該台伺服器,也就是伺服器沒有發送cookie給該台客戶端,因此客戶端的第一次請求是沒有cookie首部欄位數據的,而伺服器作為響應也會將cookie首部數據發送到該台客戶端中。
2.客戶端不是第一次請求該台伺服器,伺服器已經有發送過cookie給該台客戶端,那麼在客戶端上的cookie都會隨著請求一同發送到伺服器中,而伺服器會檢查這個cookie給你返回相應的數據,而不再需要設定cookie。
COOKIE實踐
為了能明白上面的cookie工作原理,以下進行實踐,建議讀者跟我一起做
1.還是以博客園為例,在賬戶退出的狀態下打開(https://www.cnblogs.com)[博客園首頁],使用Chrome,如果對瀏覽器開發工具比較熟悉也可以使用火狐,把網站以往的cookie清除
2.進行刷新頁面,再打開chrome開發工具network
,選擇其中的請求,點擊查看請求首部(Request Header)
以及響應首部(Response Header)
,發現響應首部有set-cookie欄位
,即伺服器給瀏覽器設置的cookie。並且,請求首部是沒有cookie欄位的,因為我們自己清除了cookie!
此時,再去查看Cookie面板發現伺服器已經給瀏覽器設置了Cookie。
再次刷新頁面。自行重覆以上步驟,發現請求首部多了一個cookie
欄位,即有了cookie後,對伺服器的每一次請求都會帶上cookie。
總結
HTTP的無狀態協議是產生Cookie技術的重要原因,cookie是伺服器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶併發送到伺服器上。cookie的主要作用就是記錄狀態,包括會話狀態管理,用戶的個性化設置,瀏覽器的行為跟蹤。
寫到這,已經涉及不少知識,文章篇幅太長不好,第二篇再寫session以及在node.JS的實踐。劇透一下,通過Node.JS操作cookie的代碼:)
const express = require('express');
const cookieParser = require('cookie-parser')
var server = express();
server.use(cookieParser('alkdukajvldfq'));
server.use('/', function(req, res) {
// 發送cookie,path是指定能訪問cookie的路徑,可從下往上讀取,反則不行,比如/=>path:/aaa
res.cookie('name', 'janro', {path: '/', maxAge: 3600*1000, signed: true});
// 讀取cookie
console.log(req.cookies);
console.log(req.signedCookies);
// / 和favicon
console.log(req.url);
res.send('OK');
//清除cookie
res.clearCookie('name');
});
server.listen(8080);
下次,session見。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!
Reference
- https://segmentfault.com/a/1190000004556040
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
- https://segmentfault.com/a/1190000007579928
- 圖解HTTP
- JavaScript高級程式設計