筆記 - 使用者角色權限驗證實作

這篇紀錄建立好使用者登入之後,取得登入中使用者資訊,並建立 middleware 驗證使用者角色的作法。

取得登入中的使用者資訊

取得登入中使用者資訊的目的,包括可以給前端運用,根據使用者的狀態來切換畫面的元件;後端也可以設計不同角色權限,根據登入使用者的角色限制其可取得的資源。在 Passport 成功登入之後,會回傳 user,所以我們可以透過 req.user 取得 user instance,來獲得登入中使用者的資訊。

在實務上會獨立一個檔案來管理使用者驗證,以便日後更換驗證套件就不是透過 req.user 來取得登入使用者資訊,所以獨立一個 helper 檔案來處理,把取得登入使用者的 function 包裝成 getUser

1
2
3
4
5
6
7
// helpers/auth-helper.js
const getUser = req => {
return req.user || null
}
module.exports = {
getUser
}

在主程式或是對應的 controller 中可以引入 helpers 透過 helpers.getUser(req) 取得。

若專案包含測試時也需要包裝函式

使用 Sinon 測試模擬時,只會蓋過自訂的函式,所以我們要把 Passport 提供的方法的打包到自訂函式裡面才會讓測試程式去模擬函式的回傳值,而不能直接使用 Passport 提供的 req.userreq.isAuthenticated()

在專案根目錄下建立 _helper.js 開發環境與測試環境共用文件。(放在 helpers folder 中不能讓測試環境使用嗎?還是是要為了區分呢?)


API: getCurrentUser

透過 helpers.getUser(req) 之後製作讓前端取得登入使用者資料的 API。

1
2
3
4
5
6
7
8
getCurrentUser: async (req, res) => {
const id = helpers.getUser(req).id
const user = await User.findByPk(id, {
attributes: [ 'id' ] // 需要的欄位資料
})
if (!user) return res.json({ status: 'error', message: 'user not found' })
return res.json(user)
}

Middleware 確認登入使用者角色權限

同樣透過 helpers.getUser(req) 取得登入使用者資料,設計 middleware 來過濾不同權限的使用者。

1
2
3
4
5
6
7
8
9
10
11
12
13
// middleware/auth.js
const helpers = require('../_helpers')

const authUser = (req, res, next) => {
if (helpers.getUser(req)?.isAdmin === false) { // 根據 user 資料欄位設計
return next()
} else {
return res.status(403).json({
status: 'error',
message: 'Permission denied.'
})
}
}

完成後在路由中加入 middleware 驗證就完成了。