# 🏅 Day 30 - JWT 驗證 middleware 延續前一天,我們可以將 isAuth 作為 middlware,將需要登入後才能進入、操作的頁面或功能都帶入 isAuth middlware,確認使用者身份後再繼續執行 題目 --- 根據需求,補上 `...` 的部分完整程式碼 1. 優化 `isAuth`,確認 token 存在並確認是否為 Bearer 開頭字串。 若符合此條件則取出 JWT 字串,若未成功取得 JWT,表示使用者可能尚未登入,需回傳 401 錯誤與錯誤訊息 `'使用者尚未登入!'` ```javascript= const isAuth = handleErrorAsync(async (req, res, next) => { // 確認 token 是否存在並取出 token let token; if ( req.headers.authorization && req.headers.authorization....('...') ) { token = req.headers.authorization.split(' ')[1]; } // token 不存在,回傳錯誤訊息 if (!token) { return appError(...); } // 驗證 token 正確性 const decoded = await new Promise((resolve,reject) => { jwt.verify(token, process.env.JWT_SECRET, (err, payload) => { if (err) { reject(err) } else { resolve(payload) } }); }); // 在資料庫尋找對應 id 的使用者 const currentUser = await User.findById(decoded.id); // 在 req 物件加入 user 欄位,並由 next() 帶到 handleErrorAsync(async(req,res,next)=>{...}) req.user = currentUser; next(); }); ``` 2. 設計取得個人資料路由 `GET /users/profile`,加入 isAuth middleware,當 request 帶上的 token 驗證通過,就將取出的 user 資料回傳給 client `routes/users.js` ```javascript= router.get('/profile', ..., handleErrorAsync(async (req, res, next) =>{ res.status(200).json({ status: 'success', user: ... }); })) ``` ## 回報流程 將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: 1. isAuth ```javascript= const isAuth = handleErrorAsync(async (req, res, next) => { // 確認 token 是否存在並取出 token let token; if ( req.headers.authorization && req.headers.authorization.startsWith('Bearer') ) { token = req.headers.authorization.split(' ')[1]; } // token 不存在,回傳錯誤訊息 if (!token) { return appError(401, '使用者尚未登入!', next); } // 驗證 token 正確性 const decoded = await new Promise((resolve,reject) => { jwt.verify(token, process.env.JWT_SECRET, (err, payload) => { if (err) { reject(err) } else { resolve(payload) } }); }); // 在資料庫尋找對應 id 的使用者 const currentUser = await User.findById(decoded.id); // 在 req 物件加入 user 欄位,並由 next() 帶到 handleErrorAsync(async(req,res,next)=>{...}) req.user = currentUser; next(); }); ``` 2. routes/users.js ```javascript= router.get('/profile', isAuth, handleErrorAsync(async (req, res, next) =>{ res.status(200).json({ status: 'success', user: req.user }); })) ``` --> 回報區 --- <!-- 將答案貼至下方表格內,格式: | Discord 暱稱 | [CodePen](連結) | --> | Discord | CodePen / 答案 | |:-------------:|:-----------------:| | xxx | [CodePen]() | |lobinda|[HackMD](https://hackmd.io/@Lobinda/HkRby9bX0)| |jenny7532|[CodePen](https://codepen.io/wei-chen-wu/pen/BaeNPgL)| |Chia Pin|[CodePen](https://codepen.io/joker-cat/pen/MWdwPPa)| |wei|[CodePen](https://hackmd.io/@xu7yoa5cSsqaron7h9XhUw/HyRhxJzXC)| |william_hsu|[CodePen](https://codepen.io/william8815/pen/VwOLgzM)| |ej_chuang|[CodePen](https://codepen.io/EJChuang/pen/VwOLNVj)| |苡安|[hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/ByHwTRM7C)| |william威良|[CodePen](https://codepen.io/snowman12320/pen/LYopNwO?editors=1010)| |Hank|[CodePen](https://codepen.io/tw1720/pen/wvbvaaL)| |Tiya|[CodePen](https://codepen.io/Tiya_blank/pen/rNbQPbY)| | runweiting |[CodePen](https://codepen.io/weiting14/pen/eYaZoPy)| |mei|[CodePen](https://codepen.io/l_umei/pen/QWRKZVM)| | fabio20 | [CodePen](https://codepen.io/fabio7621/pen/pomNZPK) |