今天,來到鐵人賽第二十四天。
話說,今日是聖誕夜。
天氣晴,可真是另類之聖誕節。
是啊,誰說聖誕節一定要下雪的?!
這麼熱血,來打鐵!
我們開始囉~
當我們了解了Cookie運作與機制,現在,我們來看看express上如何使用 cookie 做 登入。
首先,我們進入 express的官網看到,它提供了幾個cookie相關的API 參考:
res.cookie(name, value [, options])
這個有三個參數:
name: 設定cookie的名字
value: 設定其值,可能是字串或是轉成JSON格式的物件。
options: 選項參數是一個物件,所以,其屬性
放在{}裡,以逗號分隔。
◎ 分別有哪些不同的屬性
:
domain (字串) 適用此cookie的domain name
encode (函式) 用於cookie編碼的同步函式,預設encodeURIComponent.
expires (日期) cookie的到期日,超過此日期,即失效。
httpOnly (布林) 標記此cookie只能從web server 訪問,以避免不正確的進入來取得竄改。
maxAge (數字) 設定此cookie的生存時間(毫秒為單位),比方60000(10分鐘後到期,必須重新訪問)
path (字串) 適用此cookie的路徑,預設: “/”.
secure (布林) 設定此cookie是否只在https使用。
signed (布林) 此cookie是否要設簽章。(如果是true,必須使用cookie-parser設定簽章 )
res.clearCookie(name [, options])
清除cookie(登出時,可用此方法,選項與上相同)
req.signedCookies
取得由client端接收過來有設定簽章的請求,讓它形成未簽章並加以使用。
有加上簽章的cookie,好處是,只有開發者自己知道的簽章加上回應出去給個別oookie 時,使用者根本不知道你開發者簽了什麼,要竄改也難。否則,惡意攻擊容易放入req.cookie。
ex. 接收過來的 Cookie: user= ladykaka.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
當後面這一串 .CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
簽章與開發人員設定的簽章有相應,req.signedCookies.user 的值即為: ladykaka
express設定簽章,必須使用 cookie-parser middleware,它的作用是即為cookie做一個簽章。
用法:在你的express物件,加入cookieParser(your sign)
即可!
參數your sign建議是一個 128 bytes 的隨機字串。
例如:
var app=express();
app.use(cookieParser('123456789'));
接下來,我們來從無到有,實作一個express web app 並使用cookie 登入驗證功能:
mkdir login
cd login
npm init
經過初始化以後的login資料夾,就是整個login專案!
express
, body-parser
, cookie-parse
npm install express --save
npm install body-parser --save
npm install cookie-parser --save
Step3. 根據先前所學,把Login.html 靜態網頁建立好,放置在 /public/cookie/底下:
jade 樣版建立好,放置在 /views/底下。(這邊就不贅述了)
比較值得一提,login.html , post 之後的路徑,應設為:
接著,我們建立一個express web server
index.js
//載入第三方模組
var express = require('express');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//載入路由檔案
var routerCookie=require('./routes/loginAPI');
var app = express(); //建立一個express物件
//set view engine
app.set("view engine","jade")
//set view directory
app.set("views",__dirname+"/views")
//將request進來的data 轉成 json()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Create a router to handle routes for a set of loginAPI
// 抓出來, 變成獨立檔案
// -------------------------------------------------------
//靜態檔案 like .js, .json, .xml, html....
app.use(express.static(__dirname+'/public'));
// 允許 /cookie 使用這個路由
app.use('/cookie', routerCookie);
app.listen(3000,function(){
console.log('Ready...for 3000');
});
index.js
// sign for cookie
app.use(cookieParser('123456789'));
如圖:
/rotues/loginAPI.js
我們要做的事,如圖:
接下來,我們將分別說明,這三件事:
/rotues/loginAPI.js
// 表單送出後...
loginAPI.post('/post', function(req, res) {
// ...
if(req.body.firstName=="" || req.body.lastName=="")
{
return res.redirect('Login.html');
}else{
res.cookie('firstName', req.body.firstName, { path: '/cookie', signed: true, maxAge:600000}); //set cookie
res.cookie('lastName', req.body.lastName, { path: '/cookie', signed: true, maxAge:600000 }); //set cookie
return res.redirect('/cookie');
}
});
這段程式說明:
如果表單送出後,只要fristName, lastName 其中一個欄位沒有填寫,則再重回登入頁。
如果都有填了,則可以建立 cookie,在 /cookie之下有效,使用簽章,cookie 生存值100分鐘。
建好以後,導向到 /cookie 即 ….進入需要驗證的頁面。
/rotues/loginAPI.js
var isLogin=false;
// 進入需要驗證的頁面...
loginAPI.get('/',function(req,res){
// ...
var name='guest';
isLogin=false;
if(req.signedCookies.firstName && req.signedCookies.lastName){
name=req.signedCookies.firstName+ ' '+req.signedCookies.lastName;
isLogin = true;
}
res.render('index', { title: 'Express', member:name, logstatus:isLogin });
});
這段程式說明:
一開始預設,所有的登入狀態 isLogin 都是false,預設的登入者是guest。
如果,我們接收到的 cookie 皆存在,則改變 登入者姓名 及 登入狀態。
然而,無論有沒有登入,皆會導到 index.jade 樣版,去做呈現。
/rotues/loginAPI.js
// 登出...
loginAPI.get('/logout', function(req, res) {
// ...
res.clearCookie('firstName',{path:'/cookie'});
res.clearCookie('lastName',{path:'/cookie'});
return res.redirect('/cookie');
});
這段程式說明:
登出做清理的動作,並返回路由 /cookie
最後,完成的Demo,畫面像這樣:
登入前...
登入後...
完整程式檔案可於這裡下載:
https://github.com/circleuniv/login