一贴汪、關(guān)于Cookie
在我們關(guān)閉一個登錄過的網(wǎng)址并重新打開它后,我們的登錄信息依然沒有丟失休吠;當我們?yōu)g覽了商品后歷史記錄里出現(xiàn)了我們點擊過的商品扳埂;當我們推回到首頁后,推薦商品也為我們選出了相似物品瘤礁;事實上當我們有過此類操作后阳懂,瀏覽器會將我們的操作信息保存到cookie上面。阿進而言之蔚携,cookie就是儲存在用戶本地終端上的數(shù)據(jù)希太。
Cookie的特點
- cookie保存在瀏覽器本地,只要不過期關(guān)閉瀏覽器也會存在酝蜒。
- 正常情況下cookie不加密,用戶可輕松看到
- 用戶可以刪除或者禁用cookie
- cookie可以被篡改
- cookie可用于攻擊
- cookie存儲量很小矾湃,大小一般是4k
- 發(fā)送請求自動帶上登錄信息
二亡脑、Cookie的安裝及使用
1.安裝
cnpm install cookie-parser --save
2.引入
const cookieParser=require("cookie-parser");
3.設(shè)置中間件
app.use(cookieParser());
4.設(shè)置cookie
res.cookie("name",'zhangsan',{maxAge: 900000, httpOnly: true});
//res.cookie(名稱,值,{配置信息})
關(guān)于設(shè)置cookie的參數(shù)說明:
- domain : 域名
- name=value:鍵值對,可以設(shè)置要保存的 Key/Value邀跃,注意這里的 name 不能和其他屬性項的名字一樣
- Expires: 過期時間(秒)霉咨,在設(shè)置的某個時間點后該 Cookie 就會失效,如 expires=Wednesday, 09-Nov-99 23:12:40 GMT拍屑。
- maxAge: 最大失效時間(毫秒)途戒,設(shè)置在多少后失效 。
- secure: 當 secure 值為 true 時僵驰,cookie 在 HTTP 中是無效喷斋,在 HTTPS 中才有效 。
- Path: 表示 在那個路由下可以訪問到cookie蒜茴。
- httpOnly:是微軟對 COOKIE 做的擴展星爪。如果在 COOKIE 中設(shè)置了“httpOnly”屬性,則通過程序(JS 腳本粉私、applet 等)將無法讀取到COOKIE 信息顽腾,防止 XSS 攻擊的產(chǎn)生 。
- singed:表示是否簽名cookie, 設(shè)為true 會對這個 cookie 簽名诺核,這樣就需要用 res.signedCookies 而不是 res.cookies 訪問它抄肖。被篡改的簽名 cookie 會被服務(wù)器拒絕,并且 cookie 值會重置為它的原始值窖杀。
5.獲取cookie
req.cookies.name;
下面是一個基礎(chǔ)實例:
const express=require("express");
const cookieParser=require("cookie-parser");
var app=express();
//設(shè)置中間件
app.use(cookieParser());
app.get("/",function(req,res){
res.send("首頁");
});
//設(shè)置cookie
app.get("/set",function(req,res){
res.cookie("userName",'張三',{maxAge: 20000, httpOnly: true});
res.send("設(shè)置cookie成功");
});
//獲取cookie
app.get("/get",function(req,res){
console.log(req.cookies.userName);
res.send("獲取cookie成功漓摩,cookie為:"+ req.cookies.userName);
});
app.listen(8080);
當訪問set路由后會設(shè)置cookie,當訪問get路由后會獲取到設(shè)置的cookie值陈瘦。當然你也可以在其他頁面繼續(xù)獲取當前cookie幌甘,以實現(xiàn)cookie共享潮售。
三、多個二級域名共享cookie
只需要增加res.cookie中option對象的值锅风,即可實現(xiàn)對相應(yīng)路由下多個二級路由的cookie進行共享酥诽,代碼如下:
const express=require("express");
const cookieParser=require("cookie-parser");
var app=express();
//設(shè)置中間件
app.use(cookieParser());
app.get("/",function(req,res){
res.send("首頁");
});
//設(shè)置cookie
app.get("/set",function(req,res){
res.cookie("userName",'張三',{maxAge: 200000, httpOnly: true,domain: "ccc.com"});
res.send("設(shè)置cookie成功");
});
//獲取cookie
app.get("/get",function(req,res){
console.log(req.cookies.userName);
res.send("獲取cookie成功,cookie為:"+ req.cookies.userName);
});
app.listen(8080);
可以看到
不同的二級域名也能訪問到相同的cookie皱埠,只要滿足ccc.com這個頂級域名就行肮帐。
四、關(guān)于cookie加密
cookie加密是讓客戶端用戶無法的獲取cookie明文信息边器,是數(shù)據(jù)安全的重要部分训枢;一般的我們可以在保存cookie時對cookie信息進行加密,或者在res.cookie中對option對象的signed屬性設(shè)置設(shè)置成true即可忘巧。
使用 signed 屬性進行cookie加密
如下列代碼:
const express = require("express");
const cookieParser = require("cookie-parser");
var app = express();
app.use(cookieParser('secret'));
app.get("/",function(req,res){
res.send("主頁");
});
//獲取cookie
app.use(function(req,res,next){
console.log(req.signedCookies.name);
next();
});
//設(shè)置cookie
app.use(function(req,res,next){
console.log(res.cookie("name","zhangsan",{httpOnly: true,maxAge: 200000,signed: true}));
res.end("cookie為:"+req.signedCookies.name);
});
app.listen(8080);
簽名原理
Express用于對cookie簽名恒界,而cookie-parser則是實現(xiàn)對簽名的解析。實質(zhì)是把cookie設(shè)置的值和cookieParser(‘secret’);中的secret進行hmac加密砚嘴,之后和cookie值加“.”的方式拼接起來十酣。 當option中signed設(shè)置為true后,底層會將cookie的值與“secret”進行hmac加密际长;
如何解析
cookie-parser中間件在解析簽名cookie時做了兩件事:
- 將簽名cookie對應(yīng)的原始值提取出來
- 驗證簽名cookie是否合法
直接對cookie值加密
node為我們提供了一個核心安全模塊“crypto”耸采,它提供了很多安全相關(guān)的功能,如摘要運算工育、加密虾宇、電子簽名等。 這是如绸,我們便可很輕易的封裝一個加密模塊:
const crypto=require('crypto');
module.exports={
//MD5封裝
MD5_SUFFIX:'s5w84&&d4d473885s2025s5*4s2',
md5:function(str){
var obj=crypto.createHash('md5');
obj.update(str);
return obj.digest('hex');
}
}
之后只需要進行相應(yīng)導(dǎo)入即可
const common=require('./MD5');
var str='123456';
var str=common.md5(str+'s5w84&&d4d473885s2025s5*4s2');
console.log(str);
設(shè)置cookie代碼如下:
const express=require("express");
const cookieParser=require("cookie-parser");
var cry = require('./md5');
var app=express();
var str='hello-123';
var str=cry.md5(str+'s5w84&&d4d473885s2025s5*4s2');
//設(shè)置中間件
app.use(cookieParser());
//獲取加密cookie
app.use(function(req,res,next){
console.log(req.cookies.userName);
next();
});
//設(shè)置并加密cookie
app.use(function(req,res,next){
res.cookie("userName", str, {maxAge: 5*60*1000, httpOnly: true});
res.end("set ok");
});
app.listen(8080);
如果是在判斷登錄時嘱朽,只需將用戶輸入的賬號進行同樣加密操作在進行比較即可知道賬戶是否正確。 crypto所涉及的加密方式有很多竭沫,推薦大家都寫模塊引用燥翅,這樣更方便后期的維護。
五蜕提、關(guān)于session
session是另一種記錄客戶狀態(tài)的機制森书,與cookie保存在客戶端瀏覽器不同,session保存在服務(wù)器當中谎势; 當客戶端訪問服務(wù)器時凛膏,服務(wù)器會生成一個session對象,對象中保存的是key:value值脏榆,同時服務(wù)器會將key傳回給客戶端的cookie當中猖毫;當用戶第二次訪問服務(wù)器時,就會把cookie當中的key傳回到服務(wù)器中须喂,最后服務(wù)器會吧value值返回給客戶端吁断。 因此上面的key則是全局唯一的標識趁蕊,客戶端和服務(wù)端依靠這個全局唯一的標識來訪問會話信息數(shù)據(jù)。
設(shè)置session
我們使用express-session模塊來設(shè)置session
1.安裝express-session
cnpm install express-session --save
2.引入express-session模塊
const session=require("express-session");
3.設(shè)置session
session(options);
如下列代碼:
const express=require("express");
const session=require("express-session");
var app=express();
//配置中間件
app.use(session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: ('name', 'value',{maxAge: 5*60*1000,secure: false})
}));
app.use('/login',function(req,res){
//設(shè)置session
req.session.userinfo='張三';
res.send("登陸成功仔役!");
});
app.use('/',function(req,res){
//獲取session
if(req.session.userinfo){
res.send("hello "+req.session.userinfo+"掷伙,welcome");
}else{
res.send("未登陸");
}
});
app.listen(8080);
在session(option)中對session進行設(shè)置
session的常用方法
//設(shè)置session
req.session.username="張三"
//獲取session
req.session.username
//重新設(shè)置cookie的過期時間
req.session.cookie.maxAge=1000;
//銷毀session
req.session.destroy(function(err){
})
以下演示通過銷毀session的方式來退出登錄
const express=require("express");
const session=require("express-session");
var app=express();
//配置中間件
app.use(session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: ('name', 'value',{ maxAge: 5*60*1000,
secure: false,
name: "seName",
resave: false})
}));
app.use('/login',function(req,res){
//設(shè)置session
req.session.userinfo='張三';
res.send("登陸成功!");
});
app.use('/loginOut',function(req,res){
//注銷session
req.session.destroy(function(err){
res.send("退出登錄又兵!"+err);
});
});
app.use('/',function(req,res){
//獲取session
if(req.session.userinfo){
res.send("hello "+req.session.userinfo+"任柜,welcome to index");
}else{
res.send("未登陸");
}
});
app.listen(8080);
當我們進入到主頁時,未顯示任何信息沛厨,進入login路由后宙地,自動設(shè)置session,這是回到主頁則顯示session信息逆皮,之后進入loginOut路由已注銷session信息宅粥,再回到首頁顯示為登陸。
藥不能停5缫ァ粹胯!
日期:2021/12/9
學(xué)習(xí)參考視頻:*https://www.bilibili.com/video/BV1i7411G7kW?p=52&t=10.3
學(xué)習(xí)參考文檔參考部分相關(guān)視頻文案和課件,僅供個人學(xué)習(xí)和記錄