今天學習express的中間件,看到了express的cookie-parser和express-session中間件,就對cookie和session好奇了,於是就花了時間研究它們,總結如下。
由於HTTP協議是無狀態的,即不會記錄客戶端與服務端的連接信息,但是隨着互聯網的發展,與用戶的交互成了趨勢,故需要一種機制來記錄用戶的信息,保持用戶的狀態,比如短時間內重復訪問一個網站,可以讓直接定位到用戶最后一次瀏覽的位置,故cookie和session出現了。
cookie
cookie是客戶端請求服務器時,服務端記錄的用戶信息,存儲在客戶端,下一次客戶端發送請求時會將cookie一起發送。當客戶端訪問web服務器時,服務器會記錄用戶的信息然后在響應信息的響應頭中設置set-cookie頭部,然后存儲在客戶端,下一次再請求web服務器時請求頭中會加上cookie這一項並發送到服務器,服務器通過cookie判斷用戶是否訪問過該網站。
cookie是又時限的,有一個屬性maxAge可以設置cookie的存儲時間,超過時間后cookie會被刪除,默認的是瀏覽器關閉時清除cookie。cookie一般用於用戶的自動登錄,記住密碼等,將賬戶信息保存在cookie中,登錄時cookie被傳送到服務器完成自動登錄。
express中設置set-cookie頭
服務器中生成cookie要存儲在客戶端時,服務端主要是設置set-cookie頭,讓它隨響應信息response發送到客戶端。那么服務器端設置set-cookie頭的參數主要通過response.cookie(name,value[,options])設置,response.cookie是express中response對象設置cookie的方法:
name:cookie的名字;value:規定 cookie 的值。這兩者是必須得。
options對象是用來設置set-cookie頭部的選項:
secure:true是一個推薦選項。 但是,它需要啟用https的網站,即HTTPS是安全Cookie所必需的。 如果設置了安全性,通過HTTP訪問站點時,cookie將不會被設置。
以下面的圖為例,第一次訪問網站時,是響應頭中有設置set-cookie,和響應信息一起發送到客戶端:
第二次再訪問這個網站時,請求頭中自動的加上了cookie,隨着請求信息一起發送到服務器。
cookie-parser
cookie的值value是一串字符或者是轉化為json字符串的對象,cookie-parser是將cookie的值由字符串解析成對象的中間件,當使用cookie-parser中間件的時候,可以通過express中的request對象的cookies屬性req.cookies查看cookies的值,比如req.cookies.name。req.cookies這個屬性是一個對象,其包含了請求發送過來的cookies。如果請求沒有帶cookies,那么其值為{}。
session
session和cookie的作用是一樣的,也是存儲用戶信息,但是session是存儲在服務器端的。session還需借助cookie將唯一標識sessionID存到客戶端。當客戶端訪問web服務器時,會生成一個全局唯一標識sessionID,然后服務器會記錄用戶的信息然后存儲到該session中,由於客戶端下一次需要匹配sessionID,故需要將sessionID發送到客戶端,方法有兩種,一種就是設置set-cookie頭將sessionID發送到客戶端,另一種就是url重寫。第二次請求該網站時,請求頭中就會帶上cookie,cookie的值是就是sessionID。session一般用於用戶的身份驗證,即利用sessionID判斷用戶是否合法。
注意:session數據不會保存在cookie本身,只是sessionID。 session數據存儲在服務器端。
express-session
由於session的機制離不開cookie,故express-session中創建session時可以接收的options常見的有:cookie,name,resave,saveUninitialized,secret,store等具體可查看express-session。cookie是一個對象,里面的屬性可以有maxAge、domain、expires、httpOnly、path等。
app.use(session({
secret:'my app secret',// 用來對session id相關的cookie進行簽名
saveUninitialized:false,// 是否自動保存未初始化的會話,建議false
resave:false,// 是否每次都重新保存會話,建議false
store: new MongoStore({ //創建新的mongodb數據庫存儲session
host: 'localhost', //數據庫的地址,本機的話就是127.0.0.1,也可以是網絡主機
port: 27017, //數據庫的端口號
db: 'test-app' //數據庫的名稱。
}),
name:'test',//cookie的name,默認值是:connect.sid
cookie:{
maxAge:10*1000
}
}));
創建session后,可以在express的request對象的屬性req.session對session進行操作,比如req.session.destroy方法可以銷毀對話,req.session.save保存當前session,也可以通過req.session.id和req.sessionID查看session的id,但是只可讀,不可寫。也可用req.session.cookie查看cookie的各種屬性,比如req.session.cookie.maxAge等,req.session還可以自定義屬性,比如下面的例子中的req.session.views。
var express = require('express')
var parseurl = require('parseurl')
var session = require('express-session')
var app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
app.use(function (req, res, next) {
var views = req.session.views
if (!views) {
views = req.session.views = {}
}
// get the url pathname
var pathname = parseurl(req).pathname
// count the views
views[pathname] = (views[pathname] || 0) + 1
next()
})
app.get('/foo', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/foo'] + ' times')
})
app.get('/bar', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/bar'] + ' times')
})
cookie和session的區別
1、最大的區別應該在於存儲的地方不一樣,cookie存儲在客戶端,session存儲在服務器;
2、從安全性方面來說,cookie存儲在客戶端,很容易被竊取,暴露用戶信息,而session存儲在服務器,被竊取的機會小很多,故session的安全性比cookie高;
3、從性能方面來說,cookie存儲在瀏覽器端消耗的是用戶的資源,相對比較分散,而session消耗的服務器的內存,會造成服務器端的壓力;
4、cookie可以長期的存儲在客戶端,但是數量和大小都是有限制的;session存在服務器的時間較短,但是沒有大小的限制。