學會了前端對後端的API串接,並且實作了登入的動作
雖然很開心,但是就只有登入而已!!
換句話說,就是後端只告訴你「哦~你的帳號密碼是對的,好蚌蚌喔,讓你登入吧~」,就結束了!!
沒有做其他任何紀錄登入狀態的動作
所以就算登入成功了,也無從判斷登入狀態
今天的目標進度就是要在登入時加入Token
,利用 Token 來協助判斷帳號的登入狀態!!
當你去遊樂園玩,進場前會需要先買票,進場後玩一玩突然發現手機忘在車上沒帶,所以又出場去拿手機,這時候再進場,只要拿剛才買的票的票根就可以進去,不需要再重新買票
而 Token
就是這張票卷,只要登入一次就會把票卷給你讓你記錄下來,下次再開啟頁面帶上票卷檢查通過就不用再登入!!
接著就來實作登入時加入Token吧!!
一個帳號會對應一組token,使用瀏覽器的cookie來記錄它,因為帳號不只一個,所以cookie有可能會有紀錄多組token的情況
Token的部份使用JWT(JSON Web Token),JWT可以利用設定的密鑰對Token內容做編碼加密的動作
註: Token內容只要解密就可以看見,所以不要把敏感資訊放進去
首先開啟後端專案,來安裝 JWT 套件:
npm install jsonwebtoken
裝好之後開啟 /modules/users.module.js 引用它:
const jwt = require('jsonwebtoken');
接著我們在登入成功的resolve之前,來組合出需要的Token內容:
const payload = {
accountId: user.accountId,
username: user.username,
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30
};
組合之後來和 密鑰 一起簽章:
const token = jwt.sign(payload, 'THISISMYTOKENSECRET');
把簽好的 Token 加入回傳:
resolve({ message: '登入成功', token });
Token的部份就準備完成囉!!
註: 密鑰和有效期可以設定在config
接著規劃將Token存入cookie中,cookie存放的會是一個陣列組合像這樣:
[
//第一個token
{
token: 'aaa.bbb.ccc',
active: true
},
//第二個token
{
token: 'ddd.eee.fff',
active: false
},
]
在帳號登出之後,系統還是會記錄它的帳號資訊,以便下次快速登入使用,登出後的帳號就會是「未啟用」狀態
簡單的判斷方式: 登入中的帳號為 true,其他都是 false
了解格式內容之後,開啟 /controllers/users.controller.js,建立一個陣列:
let signinTokens = [];
把Token及啟用狀態塞進去:
signinTokens.push({ token: moduleResult.token, active: true });
最後陣列存入cookie中:
res.cookie('SigninTokens', signinTokens);
做到這邊會發現cookie怎麼存就是存不進去xD
檢查了一下發現原來是之前就忘了把開關打開
所謂的開關就是 withCredentials
這個設定,開啟之後就可以在請求時帶入cookie
注意!!在前端與後端專案都需要加入唷!!
前端的部分,開啟專案中的 main.js
加入這行:
axios.defaults.withCredentials = true;
後端的部分,開啟專案中的 app.js
,在 cors
的屬性設定中加上:
app.use(cors({
credentials: true,
...
}))
加好之後再重新登入一次,登入後到Chrome的開發人員模式就可以找到剛才存入的cookie囉~
分享一個 JWT 線上解析的網頁 - JWT
如果把剛才做的Token放進去解析會長這樣:
可以看到它馬上把你的payload內容解析出來,所以說不要把敏感資料放在這邊~
而密鑰它是解析不出來的
所以之後也會需要用到密鑰來判斷Token的真實性
用什麼密碼鎖住,就要用什麼密碼解開,像極了愛情
今日重點:
Token
就像遊樂園票卷,買了之後可以無限進出withCredentials
設定,發送請求時才會帶上cookie值今天完成了使用 cookie 儲存 Token 及 啟用狀態,但是有個嚴重的Bug,我只要登入一次,它就push一筆資料進去,登入一百次就push一百筆,而且每一筆都是 啟用中 ,像極了愛情xD
這個邏輯Bug先讓它飛一會兒吧~
有需要改進或是任何意見建議歡迎下面留言~