Node - Cookie and Session
Cookie and Session。
Cookie的特性
- Cookie無法對使用者保密:使用者可以查看所有Server端傳送到Client端的Cookie。
- 使用者可以刪除、停用Cookie:使用者擁有對Cookie的控制權。
- 正規的Cookie可能會被竄改:當Cookie對特定伺服器發出請求,而伺服器信任這請求時,等於門戶洞開,歡迎被攻擊。例如:去執行被竄改後的Cookie。因此,為了確保Cookie不被竄改,建議改用 Signed Cookie。
-
Cookie可用來進行攻擊:跨站指令攻擊(XSS)其中ㄧ項技術是使用JavaScript惡意修改Cookie的內容,因此不要信任由Client端回傳到Server端的Cookie內容。改善的方法是:
- 使用Signed Cookie:因為Server端不接受竄改過的Signed Cookie,且會重設回原本的值。
- 指定Cookie只能由伺服器修改。
- 使用者知道Cookie被濫用。
- 愛用Session,而非Cookie。Session較Cookie簡單、不浪費使用者的儲存空間、安全。
補充說明
- XSS攻擊:XSS簡單說明和範例。如果擔心Cookie被Javascript讀取和修改,則使用這段指令
setCookie("name","value",time()+86400,"/","domain",false,true);
。 其中最後一個參數是指定HttpOnly,表示Cookie不能夠被Javascript存取,目前主流瀏覽器皆有支援。 - What are “signed” cookies in connect/expressjs?:Signed Cookie的簡單說明。
外部認證
將Cookie保密是一個使得Cookie安全的必要方法,我們可以使用xkcd Password Generator或憑證來保障其安全性。這裡選用憑證。
建立一個javascript檔案 - credential.js,將憑證存放在這支檔案裡面。記得,要加到.gitignore,使其不受版本控管。
credential.js
module.exports = {
cookieSecret: 'your cookie secret goes here'
};
app.js
var credentials = require('./credential.js');
補充說明
Express裡的Cookie
安裝cookie-parser
npm install --save cookie-parser
在app.js中設定載入模組cookie-parser
var cookieParser = require('cookie-parser');
app.use(cookieParser(credentials.cookieSecret));
使用cookie-parser
設定Cookie
假設在取得首頁時,設定兩組Cookie:monster和signed_monster。
//get index page
router.get('/', function(req, res, next) {
//取得各城市的氣象相關資訊
if(!res.locals.partials){
res.locals.partials = {};
}
res.locals.partials.weather = getWeatherData();
//取得首頁時,設定兩組Cookie:monster和signed_monster
res.cookie('monster', 'nom nom');
res.cookie('signed_monster', 'nom nom', { signed: true});
res.render('index', { title: 'Index' });
});
來看看結果。
讀取Cookie
將剛剛設定的Cookie從Server端讀取。
var monsterCookie = req.cookies.monster;
var signedMonsterCookie = req.signedCookies.signed_monster;
刪除Cookie
刪除monster這個Cookie。
res.clearCookie('monster');
Cookie的屬性
- domain:可將Cookie指定給特定的子網域。
- path:控制Cookie套用的路徑。
- maxAge:指定Client端的Cookie的保留時間,意即在多久後刪除,以毫秒為單位。若忽略則會在瀏覽器關閉後刪除。也可以用expires指定到期時間。
- secure:指定這個Cookie只會透過HTTPS來傳送。
- httpOnly:指定這個Cookie只能被Server端修改。
- signed:若設定為true,則只能在
res.signedCookies
中使用,而不能在res.cookies中使用。Server端會拒絕被竄改的Signed Cookie,且重設為原本的值。
Session
使用一個內含獨一無二識別碼的Cookie,Server端會用這個識別碼來取回適當的Session資訊。
安裝並設定express-session
npm install --save express-session
在app.js中設定載入模組express-session。
var credentials = require('./credential.js'),
session = require('express-session');
app.use(cookieParser(credentials.cookieSecret));
app.use(session());
使用Session
req.session.userName = "Pusheen";
var colorScheme = req.session.colorScheme || 'dark';
console.log(req.session.userName); //Pusheen
console.log(colorScheme); //Dark
delete req.session.userName; //remove session
console.log(req.session.userName); //undefined
補充說明
- Cookie Session:將所有資訊存在Cookie中,而只將非識別碼存在Cookie中,再由識別碼跟Server拿取資料。
使用Session來實作閃爍訊息
於是我們就可以利用Session來實作在Node.js:表單處理與檔案上傳(Form Handling and File Uploads)提到的,當使用者提交表單後,直接在頁面上顯示Flash訊息來提示使用者成功送出資料。
HTML Snippet
{{#if flash}}
<div>{{{flash.message}}}</div>
{{/if}}
app.js
提交表單後,設定flash訊息。如果存在flash訊息,則列印在畫面上,然後刪除。
app.post('/newsletter', function(req, res){
var name = req.body.name || '',
email = req.body.email;
req.session.flash = {
type: 'success',
message: 'You have been signed up for the newsletter'
};
return res.redirect(303, '/thankyou');
});
index.js
取得thankyou page時列印flash訊息在畫面上。
//get thankyou page
router.get('/thankyou', function(req, res) {
res.locals.flash = req.session.flash;
res.render('thankyou', { title: 'thankyou' });
});
Demo
相關閱讀
- 使用 Node.js + Express 建構一個簡單的微博網站
- Node.js:表單處理與檔案上傳(Form Handling and File Uploads)
- Hello Node - 基本設定和簡單範例
- Node.js: 使用 express-partials 製作 Partial View
- Node.js: 使用模版引擎 Handlebars
- Node.js: 隱藏 Response Headers 資訊
由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-Node.js: Cookie and Session。
留言