hi 這里是me的總結
使用session進行身份認證以及signedCookie
session運行在服務器端蹂随,當客戶端第一次訪問服務器時藐石,可以將客戶的登錄信息保存苇羡。
當客戶訪問其他頁面時形导,可以判斷客戶的登錄狀態(tài)百匆,做出提示邑彪,相當于登錄攔截。
session可以和Redis或者數(shù)據(jù)庫等結合做持久化操作胧华,當服務器掛掉時也不會導致某些客戶信息(購物車)丟失寄症。
session的工作流程:
使用 cookie 有一個很大的弊端,cookie 中的所有數(shù)據(jù)在客戶端就可以被修改矩动,數(shù)據(jù)非常容易被偽造有巧,那么一些重要的數(shù)據(jù)就不能存放在 cookie 中了,而且如果 cookie 中數(shù)據(jù)字段太多會影響傳輸效率悲没。為了解決這些問題篮迎,就產生了 session,session 中的數(shù)據(jù)是保留在服務器端的示姿。
session 的運作通過一個 session_id 來進行甜橱。session_id 通常是存放在客戶端的 cookie 中,比如在 express 中栈戳,默認是 connect.sid 這個字段岂傲,當請求到來時,服務端檢查 cookie 中保存的 session_id 并通過這個 session_id 與服務器端的 session data 關聯(lián)起來子檀,進行數(shù)據(jù)的保存和修改镊掖。
這意思就是說,當你瀏覽一個網(wǎng)頁時褂痰,服務端隨機產生一個 1024 比特長的字符串亩进,然后存在你 cookie 中的 connect.sid字 段中。當你下次訪問時缩歪,cookie 會帶有這個字符串归薛,然后瀏覽器就知道你是上次訪問過的某某某,然后從服務器的存儲中取出上次記錄在你身上的數(shù)據(jù)。由于字符串是隨機產生的主籍,而且位數(shù)足夠 多习贫,所以也不擔心有人能夠偽造。偽造成功的概率比坐在家里編程時被鄰居家的狗突然闖入并咬死的幾率還低崇猫。
session 可以存放在 1)內存沈条、2)cookie本身需忿、3)redis 或 memcached 等緩存中诅炉,或者4)數(shù)據(jù)庫中。線上來說屋厘,緩存的方案比較常見涕烧,存數(shù)據(jù)庫的話,查詢效率相比前三者都太低汗洒;
express 中操作 session 要用到 express-session (https://github.com/expressjs/session ) 這個模塊议纯,主要的方法就是session(options),express-session會 默認使用內存來存 session溢谤,比較方便調試瞻凤,其中 options 中包含可選參數(shù)。
express-session模塊的常用參數(shù):
- secret:一個String類型的字符串世杀,作為服務器端生成session的簽名阀参。
- name:返回客戶端的key的名稱,默認為connect.sid,也可以自己設置瞻坝。
- resave:(是否允許)當客戶端并行發(fā)送多個請求時蛛壳,其中一個請求在另一個請求結束時對session進行修改覆蓋并保存。默認為true所刀。但是(后續(xù)版本)有可能默認失效衙荐,所以最好手動添加。
- saveUninitialized:初始化session時是否保存到存儲浮创。默認為true忧吟, 但是(后續(xù)版本)有可能默認失效,所以最好手動添加斩披。
- cookie:設置返回到前端key的屬性瀑罗,默認值為{ path: ‘/’, httpOnly: true, secure: false, maxAge: null }。
- store: session 的存儲方式雏掠,默認存放在內存中斩祭,也可以使用 redis,mongodb 等乡话。express 生態(tài)中都有相應模塊的支持摧玫。
- genid: 產生一個新的 session_id 時,所使用的函數(shù), 默認使用 uid2 這個 npm 包诬像。
- rolling: 每個請求都重新設置一個 cookie屋群,默認為 false。
express-session的一些方法:
Session.destroy():刪除session坏挠,當檢測到客戶端關閉時調用芍躏。
Session.reload():當session有修改時,刷新session降狠。
Session.regenerate():將已有session初始化对竣。
Session.save():保存session。
簡單的代碼示例
//app.js中添加如下代碼(已有的不用添加)
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
app.use(cookieParser('sessiontest'));
app.use(session({
secret: 'sessiontest',//與cookieParser中的一致
resave: true,
saveUninitialized:true
}));
//修改router/index.js,第一次請求時我們保存一條用戶信息榜配。
router.get('/', function(req, res, next) {
var user={
name:"Chen-xy",
age:"22",
address:"bj"
}
req.session.user=user;
res.render('index', {
title: 'the test for nodejs session' ,
name:'sessiontest'
});
});
//修改router/users.js否纬,判斷用戶是否登陸。
router.get('/', function(req, res, next) {
if(req.session.user){
var user=req.session.user;
var name=user.name;
res.send('你好'+name+'蛋褥,歡迎來到我的家園临燃。');
}else{
res.send('你還沒有登錄,先登錄下再試試烙心!');
}
})
關于signedCookie
上面提到的使用cookie 雖然很方便膜廊,但是使用 cookie 有一個很大的弊端,cookie 中的所有數(shù)據(jù)在客戶端就可以被修改淫茵,數(shù)據(jù)非常容易被偽造
其實計算機領域有個名詞叫 簽名爪瓜,我們可以用這個來使cookie變得安全和難以破解。
比如我們現(xiàn)在面臨一個網(wǎng)站痘昌,它用 cookie 來記錄登陸的用戶憑證钥勋。相應的 cookie 是這樣:dotcom_user = RoronoaZoro
,它說明現(xiàn)在的用戶是 RoronoaZoro(索铝咎Α)這個用戶算灸。如果我在瀏覽器中裝個插件,把它改成dotcom_user = Shanks
驻啤,服務器一讀取菲驴,就會誤認為我是 Shanks(香克斯)。然后我就可以進行 Shanks才能進行的操作了骑冗。如果我們把 cookie 改成 dotcom_user=admin 赊瞬,說不定可以把這個網(wǎng)站給黑掉。贼涩。巧涧。
現(xiàn)在我有一些數(shù)據(jù),不想存在 session 中遥倦,想存在 cookie 中谤绳,怎么保證不被篡改呢?那就是簽名。
假設我的服務器有個秘密字符串缩筛,是 this_is_my_secret_string
消略,我為用戶 cookie 的 dotcom_user 字段設置了個值 RoronoaZoro。cookie 本應是{dotcom_user: 'RoronoaZoro'}
這樣的瞎抛。
而如果我們簽個名艺演,比如把 dotcom_user 的值跟我的 secret_string 做個 sha1
sha1('this_is_my_secret_string' +'RoronoaZoro')===
'4850a42e3bc0d39c978770392cbd8dc2923e3d1d'
然后把 cookie 變成這樣
{
dotcom_user: 'RoronoaZoro', 'dotcom_user.sig': '4850a42e3bc0d39c978770392cbd8dc2923e3d1d',
}
這樣一來,用戶就沒法偽造信息了桐臊。一旦它更改了 cookie 中的信息胎撤,則服務器會發(fā)現(xiàn) hash 校驗的不一致。