express 使用 JWT 製作登入 token 機制

現在碰到的每個網站幾乎都會需要登入機制,就算網站的內容不用登入也可以查看,還是有很多人喜歡加一個會員登入機制,搜集使用者資訊,進行再行銷。

在公司與其他後端合作,登入機制其實就只要打後端開好的 api 就可以了,給後端帳密,他們就會回傳 token,因此我從來沒有好好了解登入是怎樣的運作,token 又是怎樣產生的XD

最近剛好要做一個自己登山要用的系統,裡面存放有一些敏感資訊,但是又想要把網站上線給其他山友使用,所以就想做一個登入機制,讓本女王幫你創建帳號才可以進去看^3 ^ ~~

由於原理我也是上網查資料的,都是別人辛苦寫作的心血,這邊就不複製貼上了,著重在我自己實驗的結果。

大綱:

  1. 安裝 jsonwebtoken
  2. 登入時回傳token
  3. 使用 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帶在headerauthorization裡,讓後端去解析。

先說明我前端帶的headers

headers: {
    authorization: `Bearer ${token}`
}

所以我預期後端會收到Bearer ${token}這樣的字段,必須把其中的token解析出來,然後使用 jsonwebtokenverify方法去驗證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的差別。

| 軟體開發 | 網站建置 | 網頁系統 | 資料庫網站 |

| 客製化網站 (報名系統、投票系統、掛號系統...) |

| 前後端技術合作 |

歡迎與我們聯繫:jessica@penueling.com

加入Line立即聊聊:@539mjyid

0
0 回復

發表評論

Want to join the discussion?
Feel free to contribute!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。