Token Bug 已經讓它飛很久了,是時候開殺了~
首先規劃要回到原本controller及module的初衷,controller負責中介,而資料處理留給module
開啟 /modules/user.module.js
新增 getSigninTokens,傳入值為 request 及 Token,把原來的code貼進來:
const getSigninTokens = (req, token) => {
let signinTokens = [];
signinTokens.push({ token: moduleResult.token, active: true });
return signinTokens;
};
最下方記得匯出:
module.exports = {
...,
getSigninTokens
};
而 /controllers/users.controller.js 改為呼叫module:
res.cookie('SigninTokens', userModule.getSigninTokens(req, moduleResult.token));
接著開始改寫邏輯!!
第一行判斷請求時帶入的token陣列,有就帶入,沒有就維持空陣列:
let signinTokens = req.cookies.SigninTokens ? req.cookies.SigninTokens : [];
將陣列中所有項目的啟用狀態都改為 false:
signinTokens.forEach(function (item) { item.active = false; });
從陣列中找到和登入帳號相同的項目:
let signinToken = signinTokens.find(function (item) {
let accountId = jwt.verify(item.token, config.jwt.tokensecret, (error, decoded) => {
return decoded.accountId;
});
return accountId === req.body.accountId;
});
這裡用到 JWT 的解密方法:
要解密的Token
, 密鑰
, callback function)
陣列中有相同項目的話,代表有登入過,就直接更新Token和啟用狀態就好,沒有相同項目的話就push一筆新的上去:
if (signinToken) {
signinToken.token = token;
signinToken.active = true;
} else {
signinTokens.push({ token, active: true });
}
const getSigninTokens = (req, token) => {
let signinTokens = req.cookies.SigninTokens ? req.cookies.SigninTokens : [];
signinTokens.forEach(function (item) { item.active = false; });
let signinToken = signinTokens.find(function (item) {
let accountId = jwt.verify(item.token, config.jwt.tokensecret, (error, decoded) => {
return decoded.accountId;
});
return accountId === req.body.accountId;
});
if (signinToken) {
signinToken.token = token;
signinToken.active = true;
} else {
signinTokens.push({ token, active: true });
}
return signinTokens;
};
改寫完就不會再有登入一次寫一次,登入一百次寫一百次的狀況囉!!
cookie本身也能做簽章加密的動作
先說一下為什麼需要把cookie做簽章加密?
試想,既然我們都能在Chrome開發模式下看到它,想必竄改它的資料也不是什麼難事
而加上簽章加密後,對方無法知道密鑰,就算竄改了資料也能判斷出來,可有效做預防
開啟 app.js
,找到其中的 app.use(cookieParser());
這段,將密鑰加進 cookieParser() 參數:
app.use(cookieParser('THISISMYCOOKIESECRET'));
密鑰可以寫進設定檔中引用
開啟 /controllers/users.controller.js
在存入 cookie 的程式碼後方加上 { signed: true }
參數設定,設定在寫入cookie時要做簽章加密的動作!!
res.cookie('SigninTokens', userModule.getSigninTokens(req, moduleResult.token), { signed: true });
開啟 /modules/user.module.js
原本取得 cookies 的部分都要改為抓已簽章的 signedCookies:
let signinTokens = req.signedCookies.SigninTokens ? req.signedCookies.SigninTokens : [];
三個地方改好就完成cookie簽章加密囉~
可以自己玩看看,到開發模式去竄改cookie值,會發現改了之後 req.signedCookies
這段就抓不到囉~
今日重點:
有需要改進或是任何意見建議歡迎下面留言~