文章大綱
現在碰到的每個網站幾乎都會需要登入機制,就算網站的內容不用登入也可以查看,還是有很多人喜歡加一個會員登入機制,搜集使用者資訊,進行再行銷。
在公司與其他後端合作,登入機制其實就只要打後端開好的 api 就可以了,給後端帳密,他們就會回傳 token
,因此我從來沒有好好了解登入是怎樣的運作,token
又是怎樣產生的XD
最近剛好要做一個自己登山要用的系統,裡面存放有一些敏感資訊,但是又想要把網站上線給其他山友使用,所以就想做一個登入機制,讓本女王幫你創建帳號才可以進去看^3 ^ ~~
由於原理我也是上網查資料的,都是別人辛苦寫作的心血,這邊就不複製貼上了,著重在我自己實驗的結果。
大綱:
- 安裝 jsonwebtoken
- 登入時回傳
token
- 使用 middleware
安裝 jsonwebtoken
$ yarn add jsonwebtoken
登入時回傳token
jsonwebtoken 產生token
的寫法是sign
,他會需要使用一組你自己定義的密碼去進行編碼,我習慣把有敏感資訊的內容另外放在一個config
檔裡面,這個config
檔案是不能上傳到公開倉庫的,像是 jwt 密碼、資料庫帳密…等。
const jwt = require("jsonwebtoken");
const config = require("./config");
const token = jwt.sign({ username, password }, config["JWT_SIGN_SECRET"]);
產生出來的token
會需要在你 從資料庫判斷前端傳來的帳密都正確 之後,回傳給前端。
整個 api 完整程式碼:
const { Router } = require("express");
const jwt = require("jsonwebtoken");
const query = require("../../helpers/query");
const config = require("../../helpers/config");
const router = Router();
router.post("/login", async function (req, res) {
try {
const { username, password } = req.body;
const user = await query(
`SELECT username,password FROM User WHERE username='${username}' `
);
if (!user.length) {
res.status(404).json({ msg: "帳號輸入錯誤" });
return;
} else if (user[0].password !== password) {
res.status(403).json({ msg: "密碼錯誤" });
return;
}
const token = jwt.sign({ username, password }, config["JWT_SIGN_SECRET"]);
res.status(200).json({ token });
} catch (error) {
console.log(error);
res.status(500).json({ msg: "err" });
}
});
module.exports = router;
這樣前端在輸入完帳密,打登入的 api 成功後,就會收到一組 token
。

使用 middleware
在登入之後要打的每一隻 api,後端都需要經過token
驗證,所以在這邊我的前端會先把拿到的token
存起來,在打需要權限的 api 的時候,把token
帶在header
的authorization
裡,讓後端去解析。
先說明我前端帶的headers
:
headers: {
authorization: `Bearer ${token}`
}
所以我預期後端會收到Bearer ${token}
這樣的字段,必須把其中的token
解析出來,然後使用 jsonwebtoken 的verify
方法去驗證token
是否有效:
const token = req.headers['authorization'].split(' ')[1];
jwt.verify(token, config['JWT_SIGN_SECRET'], function (err, decoded) {
//...
});
如果token
失效或是根本就錯誤的話,拋出一個401
錯誤,其實要拋出幾號錯誤只要協議好就可,但還是有一些號碼是大家都這麼認定的錯誤代碼。
新增一隻檔案middleware.js
,完整的程式碼:
var jwt = require('jsonwebtoken');
const config = require('./config');
const authentication = (req, res, next) => {
let token;
try {
token = req.headers['authorization'].split(' ')[1];
} catch (e) {
token = '';
}
jwt.verify(token, config['JWT_SIGN_SECRET'], function (err, decoded) {
if (err) {
return res.status(401).json({ message: 'Unauthorized!' });
} else {
next();
}
});
};
module.exports = authentication;
在所有的 api router 中使用:
const { Router } = require("express");
const query = require("../../helpers/query");
const authenticationMiddleware = require("../../helpers/middleware");
const router = Router();
router.use(authenticationMiddleware); // <-- 在所有api最上面引用剛剛新增的miidleware
router.get("/customers", async function (req, res) {
// ...
});
router.post("/customer", async function (req, res) {
// ...
});
module.exports = router;
可以使用 postman 打打看這些有使用 miidleware 的api,實驗一下有帶入token
與沒有帶入token
的差別。
發表評論
想要加入討論嗎?請盡情發表您的想法!