node.js學(xué)習(xí)(11)——cookie和session的使用

上一節(jié)-node.js學(xué)習(xí)(10)—express中間件—body-parser獲取post杈湾、get數(shù)據(jù)

上節(jié)我們講了如何在express中獲取post懂拾、get數(shù)據(jù)析恢,這一節(jié)我們講解cookie和session。


20190523164210.png

1.給瀏覽器發(fā)送( response ) cookie

我們在server.js添加如下代碼

const express=require('express');
const server=express();

server.use('/test', function (req, res){
    if (req.url === '/favicon.ico') {
        return
    }
    res.cookie('user', 'blue'); //發(fā)送cookie給瀏覽器键兜,讓瀏覽器來寫入cookie
    res.send('hello cookie');
});

server.listen(8080);
  1. 在express中凤类,它已經(jīng)為我們封裝好了操作cookie的方法,我們使用res.cookie來發(fā)送cookie
  2. 上面代碼表示在 /test路徑下,設(shè)置cookie為key:user,value:blue
  3. 如果設(shè)置多個cookie普气,需要寫多行res.cookie
  4. 除下設(shè)置key/value谜疤,還可以添加其他參數(shù),如path,http,domain.maxAge,expires等现诀,具體可以看express文檔-res.cookie
    res.cookie('user', 'blue',{
        path:'/',
        httpOnly:false
        ...
    })

啟動服務(wù)夷磕,打開瀏覽器并訪問/test路徑,我們可以在控制臺找到我們剛設(shè)置的cookie仔沿。

20190520163526.png

2.服務(wù)器接收瀏覽器傳過來的( request ) cookie

上面我們講了服務(wù)端如何發(fā)送cookie給瀏覽器坐桩,并且也知道瀏覽器訪問服務(wù)器url,會先檢查url下有沒有cookie,有的話在訪問過程中封锉,會將cookie自動添加到請求頭中绵跷,那么服務(wù)器如何從請求頭中獲取cookie呢?

我們修改server.js

const express=require('express');
const cookieParser=require('cookie-parser');
const server=express();
server.use(cookieParser())
server.use('/test', function (req, res){
    if (req.url === '/favicon.ico') {
        return
    }
    res.cookie('user', 'blue'); //設(shè)置cookie
    res.cookie('user1', 'blue1'); //設(shè)置cookie
    console.log(req.cookies) //{"user": "blue","user1":"blue1"}
    res.send(req.cookies);
});

server.listen(8080);
  1. express默認(rèn)需要引入cookie-parser模塊(安裝express會自動安裝成福,不用單獨(dú)安裝碾局,只需要引入即可)才能獲取瀏覽器傳過來的cookie。
  2. 使用req.cookies獲取瀏覽器傳過來的cookie,值為對象闷叉。

在瀏覽器中運(yùn)行上面代碼擦俐,如下圖:

  1. 第一次req.cookies為空,瀏覽器寫入cookie
  2. 第二次瀏覽器發(fā)送之前寫入的cookie握侧,req.cookies有值
rrr.gif

3.cookie簽名(防服務(wù)器數(shù)據(jù)篡改)

何謂篡改蚯瞧,我們都知道,cookie是保存在客戶端的品擎,我們可以通過js或者直接在控制臺修改cookie的埋合,這樣會暴露一個問題:

  1. 瀏覽器發(fā)起一個修改用戶信息的請求,帶上Cookie信息username=aa(前提已經(jīng)種下cookie)萄传,服務(wù)器接收到請求后甚颂,會去修改username為aa的數(shù)據(jù)
  2. 如果用戶知道username字段表示用戶名信息,那么他把值改為bb秀菱,然后再次發(fā)起請求振诬,服務(wù)器接收到請求,去修改username為bb用戶的數(shù)據(jù)(假如數(shù)據(jù)庫中剛好有個username為bb的用戶)
  3. 這樣因?yàn)閏ookie被用戶修改衍菱,導(dǎo)致服務(wù)器數(shù)據(jù)被篡改的風(fēng)險

怎么防止篡改赶么?就有了cookie簽名的由來。

  1. 假設(shè)現(xiàn)在有個cookie(username=blue),服務(wù)器在發(fā)送cookie給瀏覽器之前先配置一個秘鑰(如sdfjk7777)脊串,通過sha256或者其他加密算法(這里假設(shè)加密方法為secret())辫呻,然后使用secret('blue','sdfjk7777')生成一個簽名和cookie值組合(類似{username:s:blue.3byMSHd31XkJ0JszpW7IXndQaUh6XFLxks+6/zWRdXg}
  2. 其中blue表示真正的值清钥,后面是簽名。假如我現(xiàn)在把blue改成blue1放闺。
  3. 當(dāng)瀏覽器再次發(fā)送請求時祟昭,服務(wù)器取出簽名(因?yàn)樘L了,這里叫A)以及cookie真正的值(blue1)怖侦。然后使用之前的加密算法判斷secret('blue1','sdfjk7777')==A篡悟,如果不相等,說明cookie被惡意修改了础钠。

4.使用cookie-parser增加cookie簽名

我們修改server.js

const express=require('express');
const cookieParser=require('cookie-parser');
const server=express();
//增加一個隨機(jī)秘鑰
server.use(cookieParser('asdfd45556'))

server.use('/test', function (req, res){
    if (req.url === '/favicon.ico') {
        return
    }
    res.cookie('user', 'blue',{
        signed:true
    });
    res.cookie('user1', 'blue1'); 
    console.log(req.cookies); //無簽名cookie {user1:blue1}
    console.log(req.signedCookies); //簽名cookie {user:blue}
    console.log(req.headers.cookie) //瀏覽器發(fā)過來的cookie: user1=blue1; user=s%3Ablue.3byMSHd31XkJ0JszpW7IXndQaUh6XFLxks%2B6%2FzWRdXg
    res.send('ok'); //由于res.send默認(rèn)最后一個生效(相當(dāng)于只能寫一個)恰力,所以上面用console.log代替輸出
});

server.listen(8080);
  1. 將秘鑰 asdfd45556傳入cookieParser函數(shù)中叉谜,然后在需要簽名的cookie增加參數(shù) signed:true
  2. 此時cookie會分割成兩個屬性 cookies-未簽名的旗吁、signedCookies-已簽名的
  3. 注意:req.signCookies的值為簽名的cookie原始值,不帶簽名字符串停局,閱讀cookie-parser源碼很钓,其將簽名去除然后再賦到signCookies上
  4. 可以通過req.header.cookie獲取瀏覽器帶過來的cookie
20190521163546.png

上圖中,s%3Ablue.3byMSHd31XkJ0JszpW7IXndQaUh6XFLxks%2B6%2FzWRdXg為簽名cookie董栽,實(shí)際上是該值是先簽名后encodeURIComponent編碼過來的码倦。我們可以解碼看

console.log(decodeURIComponent('s%3Ablue.3byMSHd31XkJ0JszpW7IXndQaUh6XFLxks%2B6%2FzWRdXg')) 
//s:blue.3byMSHd31XkJ0JszpW7IXndQaUh6XFLxks+6/zWRdXg

其中,s:表示簽名锭碳,blue為真正的值袁稽,后面的是簽名

所以我們在瀏覽器實(shí)際上仍可以看見用戶信息,cookie簽名并不能起到加密作用擒抛,只是防篡改作用推汽。

5.cookie-session

之前在cookie和session區(qū)別曾講過seesion。下面我們通過nodejs來實(shí)現(xiàn)session的demo(判斷用戶是否來過歧沪,保持用戶登陸狀態(tài))

server.js代碼如下:

const express=require('express');
// const cookieParser=require('cookie-parser');
const cookieSession=require('cookie-session');
const server=express();
// server.use(cookieParser())
server.use(cookieSession({
    keys: ['aaa', 'bbb', 'ccc'], //session用來生成簽名的列表,必填
    name: 'sessionId', //session名字歹撒,可省略,實(shí)測默認(rèn)名字為'express:sess'
    cookie:{      //session配置
        //cookie選項(xiàng)
        path:'',
        ...
    }
}))

server.get('/test', function (req, res){
    if (req.url === '/favicon.ico') {
        return
    }
    console.log(req.session); //第一次為{}诊胞,后面為{hasCome:true}
    // console.log(req.cookies); 
    // console.log(req.signedCookies); 
    if(!req.session['hasCome']){
        req.session['hasCome']=true //寫入hasCome屬性
        res.send('歡迎第一次');
    }else{
        res.send('歡迎再次來');
    }
});

server.listen(8080);
  1. 使用session依賴cookie-session中間件暖夭,和cookie-parse不一樣,需要單獨(dú)安裝撵孤,express不帶迈着。
  2. 該中間件使用必須傳一個key數(shù)組,用來的session進(jìn)行簽名邪码,和cookie簽名一樣裕菠,用來防止篡改,校驗(yàn)霞扬。name可以不傳默認(rèn)為express:sess
  3. 使用該中間件,session保存在cookie中糕韧,所以額外配置項(xiàng)就是cookie選項(xiàng)枫振。所以如果expires/maxAge不傳,即N/A萤彩,會話cookie,瀏覽器關(guān)閉即過期粪滤。
  4. 引入該中間件,req上面會增加session屬性雀扶。demo中第一次進(jìn)來session為空杖小,不存在hasCome屬性(判斷是否已經(jīng)來過),所以寫入該屬性,頁面返回歡迎第一次愚墓,后面再次訪問予权,req.session為{hasCome:true},頁面返回歡迎再次來浪册,可以看下圖req.session打印狀態(tài)以及頁面展示內(nèi)容
tesw.gif
  1. 我們通過req.session可以很方便的訪問session扫腺,由于該session對應(yīng)的id是保存在cookie中,所以我們?nèi)钥梢砸胏ookie-parser在cookie中查看sessionId(注意:雖然sessionId有簽名村象,但是該插件將sessionId存在req.cookies屬性中笆环,不在req.signedCookies中,所以通過req.signedCookies是無法訪問到的)

現(xiàn)在我們把之前server.js的代碼中注釋的cookie-parser等代碼解開注釋厚者,可以看到打印結(jié)果:

console.log(req.cookies) 
//結(jié)果為
{
  sessionId: 'eyJoYXNDb21lIjp0cnVlfQ==',
  'sessionId.sig': 'moOOM66p-CAR9aeTORKkuBYXFk4'
}

console.log(req.signCookies) 
//結(jié)果為
{}
  1. 從session的格式來看躁劣,簽名是單獨(dú)為一個sessionId.sig字段,和之前使用cookie-parser簽名一個cookie不一樣(之前直接在cookie上拼接簽名)
20190523154833.png
  1. 如果session值變化库菲,sessionId以及簽名sessionId.sig會跟著變化账忘。我們再換個demo(記錄頁面訪問次數(shù))測試下

更改server.js代碼:

const express=require('express');
const cookieSession=require('cookie-session');
const server=express();
server.use(cookieSession({
    keys: ['aaa', 'bbb', 'ccc'],
    name: 'sessionId', 
}))

server.get('/test', function (req, res){
    if (req.url === '/favicon.ico') {
        return
    }
    //count字段表示頁面訪問次數(shù)
    if(!req.session['count']){
        req.session['count']=1
    }else{
        req.session['count']++
    }
    res.send(''+req.session['count'])
});

server.listen(8080);

頁面測試結(jié)果:

count1.gif

下一節(jié)-node.js學(xué)習(xí)(12)—nodejs模板引擎jade(1)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熙宇,隨后出現(xiàn)的幾起案子鳖擒,更是在濱河造成了極大的恐慌,老刑警劉巖奇颠,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件败去,死亡現(xiàn)場離奇詭異,居然都是意外死亡烈拒,警方通過查閱死者的電腦和手機(jī)圆裕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荆几,“玉大人吓妆,你說我怎么就攤上這事《种” “怎么了行拢?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诞吱。 經(jīng)常有香客問我舟奠,道長竭缝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任沼瘫,我火速辦了婚禮抬纸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘耿戚。我一直安慰自己湿故,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布膜蛔。 她就那樣靜靜地躺著坛猪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪皂股。 梳的紋絲不亂的頭發(fā)上墅茉,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機(jī)與錄音屑墨,去河邊找鬼躁锁。 笑死,一個胖子當(dāng)著我的面吹牛卵史,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搜立,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼以躯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了啄踊?” 一聲冷哼從身側(cè)響起忧设,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颠通,沒想到半個月后址晕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顿锰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年谨垃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硼控。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡刘陶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出牢撼,到底是詐尸還是另有隱情匙隔,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布熏版,位于F島的核電站纷责,受9級特大地震影響捍掺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜再膳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一乡小、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饵史,春花似錦满钟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吭露,卻和暖如春吠撮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讲竿。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工泥兰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人题禀。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓鞋诗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親迈嘹。 傳聞我的和親對象是個殘疾皇子削彬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349