簡介
創(chuàng)新互聯(lián)公司專業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專業(yè)提供成都服務(wù)器托管,服務(wù)器租用,資陽服務(wù)器托管,資陽服務(wù)器托管,成都多線服務(wù)器托管等服務(wù)器托管服務(wù)。
express-session
是express中的一個處理session的中間件,可以說是express中最常見的中間件之一了.
由于會話管理依賴cookie的使用,所以它的api中有很多用于控制cookie的部分.
總的來說express-session
有如下的特點(diǎn):
本文中使用的版本為1.15.6
.
安裝
npm install express-session --save
引入&使用
const express = require('express'); const app = new express(); const expressSession = require('express-session'); // 使用express-session app.use(expressSession({ secret:'hello world',// cookie簽名 這個屬性是必須的 具體配置和`cookie-parser`一樣 saveUninitialized:true, // 是否自動初始化 默認(rèn)為true resave:false,// 當(dāng)用戶session無變化的時候依然自動保存 cookie:{ // cookie的信息具體操作和`cookie-parser`一樣 maxAge:1800000// 30分鐘后過期 }, rolling:true// 每次請求的時候覆寫cookie }))
會話簡介
在express-session文檔中有如下的一句說明:
Note Session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
Session中包含的數(shù)據(jù)不會保存在cookie中,僅僅是在cookie中保存了一個SessionId而已.實(shí)際的session的數(shù)據(jù)保存在服務(wù)端.
簡單理解就是一個Map,鍵對應(yīng)的是session id值保存在cookie中,值對應(yīng)的是用戶保存在服務(wù)端的數(shù)據(jù).
api介紹
參數(shù)
創(chuàng)建express-cookie
參數(shù)基本分為兩種.
cookie設(shè)置一覽:
app.use(expressSession({ secret:'hello world', // cookie 簽名必須有否則會報錯 cookie:{ domain:<參數(shù)>, expires:<參數(shù)>, httpOnly:<參數(shù)>, path:<參數(shù)>, sameSite:<參數(shù)>, secure:<參數(shù)>, maxAge:1800000 } }));
而這些對應(yīng)的參數(shù)就是服務(wù)端對于cookie的寫入?yún)?shù),至于各個參數(shù)是什么意思參考下面的文章:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie
express-session部分設(shè)置:
app.use(expressSession({ secret:'hello world', // cookie 簽名必須有否則會報錯 genid:function (request) { // 用于替換掉默認(rèn)ID生成的函數(shù) 第一個參數(shù)為reqeust return '隨機(jī)id' }, name:'connect.sid',// 每次響應(yīng)中向cookie中起始的內(nèi)容,默認(rèn)起始為`connect.sid`, proxy:true,// 對于cookie使用secure后,在傳遞的過程中相信反向代理服務(wù)器,默認(rèn)為undefined只相信正向代理 resave:true,// 在一次會話中無論是否session被改變都會進(jìn)行強(qiáng)制的儲存 rolling:true,// 在每次會話中的響應(yīng)中都覆寫一次cookie,重置倒計時 saveUninitialized:true,// 將一個新創(chuàng)建還未修改的會話進(jìn)行儲存,默認(rèn)為true store:object// 一個儲存對象,默認(rèn)使用的是`MemoryStore`這個存儲器 unset:'keep'// 控制沒有設(shè)置`req.session`時候的行為(使用delete刪除或者賦值null),默認(rèn)'keep'會話期間不會保留,'destroy'會話完成后刪除. }));
方法
在request.session
上掛載的session
對象,除了有你添加的內(nèi)容外,還有默認(rèn)的方法存在:
req.session.regenerate(function(err) { // 調(diào)用這個方法從新生成一個新的會話,完成后觸發(fā) }) req.session.destroy(function(err) { // 刪除這個會話,完成后觸發(fā) }) req.session.reload(function(err) { // 從新加載session數(shù)據(jù),完成后觸發(fā)回調(diào) }) req.session.save(function(err) { // 使用當(dāng)前內(nèi)存中的數(shù)據(jù)保存到儲存器中 // 默認(rèn)在會話結(jié)束的時候就會自動調(diào)用這個方法 }) req.session.touch() // 更新cookie中的maxAge,一般不需要手動操作,交由中間件
屬性
同樣的在session實(shí)例上也有很多屬性:
req.session.id // 保存唯一的會話id值,不可修改 req.session.cookie // 以鍵值對的形式保存cookie的原始數(shù)據(jù) req.session.cookie.maxAge // 以毫秒的形式返回剩余存活時間 req.sessionID // 保存唯一的會話id,只讀
一個簡單的例子
一個簡單的登錄例子:
const express = require('express'); const app = new express(); const expressSession = require('express-session'); const userDb = new Map(); app.use(expressSession({ secret:'hello world', saveUninitialized:true, resave:false, cookie:{ maxAge:1800000 }, rolling:true, })); app.get('/login', (request, response) => { const id = request.query.id, pwd = request.query.pwd; if(id && pwd){ if(userDb.has(id+pwd)){ response.send('該用戶已登錄'); }else{ request.session.userId = id+pwd; userDb.set(id+pwd,id); response.redirect('/'); } }else{ response.send('請輸入正確的帳號和密碼'); } }); app.get('/logout',(request, response)=>{ const userId = request.session.userId; request.session.destroy((err)=>{ if(err || !userDb.has(userId)){ response.send('登出失敗'); }else{ userDb.delete(userId); response.send('登出成功'); } }); }); app.get('/',(request, response)=>{ if(request.session.userId && userDb.has(request.session.userId)){ response.send(`歡迎回來${userDb.get(request.session.userId)}`); }else{ response.send('還未登錄'); } }); app.use((request, response) => { response.send('404 not found'); }); app.listen(8888, '127.0.0.1');
在瀏覽器中依次輸入以下url來模擬登錄行為:
localhost:8888/ localhost:8888/login?id=ASCll&pwd=123456 localhost:8888/ localhost:8888/logout localhost:8888/
暗坑
我在chrome瀏覽器下運(yùn)行上面的例子多次后發(fā)現(xiàn)一個問題,瀏覽器會進(jìn)行預(yù)讀取網(wǎng)頁來提高性能,也就是說在瀏覽器中當(dāng)我url輸入到如下的地方時:
localhost:8888/logo
根據(jù)我之間多次進(jìn)入這個頁面瀏覽器會提前訪問這個頁面localhost:8888/logout
,而導(dǎo)致服務(wù)器直接刪除session
等到真正進(jìn)入到頁面的時候已經(jīng)是第二次加載頁面了,導(dǎo)致每次登出都顯示失敗.
希望有經(jīng)驗(yàn)的朋友能給出一個合理的解決方案.
注意
當(dāng)express-session
和cookie-parser
一起使用的時候?qū)τ?code>cookie的簽名必須一致.
express-session
的存儲實(shí)例是可以更換的,默認(rèn)使用MemoryStore
只適合于測試和開發(fā)使用,生產(chǎn)環(huán)境必須要使用其他的儲存實(shí)例,否則會出現(xiàn)內(nèi)存碎片問題,在官方文檔中給出了已經(jīng)實(shí)現(xiàn)的接口,可以對接redis
以及MongoDB
等數(shù)據(jù)庫.
該列表在官方文檔的最后:
npm地址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。