---
# System prepended metadata

title: "\U0001F3C5 Day 29"
tags: [Node.js 直播班 - 2022 春季班]

---

---
tags: Node.js 直播班 - 2022 春季班
---
# 🏅 Day 29



## 登入功能


**密碼解密**
若使用者成功註冊，密碼被加密後，未來需要驗證是否為該註冊帳號可使用 `compare()` 將密碼與加密後的字串進行比對

```javascript
// 尋找資料庫符合接收到的使用者資料，因 password 欄位在 schema 通常設定為不顯示，因此可使用 select() 將密碼顯示出來
const user = await User.findOne({ email }).select('+password');
bcrypt.compare(password, user.password);
// 第一個參數是接收到的密碼，第二個參數是由資料庫找出的該 user 的密碼，為雜湊加密的字串
```




### 參考資源
[bcryptjs - compare](https://github.com/dcodeIO/bcrypt.js#compares-hash-callback-progresscallback)
[mongoose select()](https://mongoosejs.com/docs/api/query.html#:~:text=When%20using%20string%20syntax%2C%20prefixing%20a%20path%20with%20%2D%20will%20flag%20that%20path%20as%20excluded.%20When%20a%20path%20does%20not%20have%20the%20%2D%20prefix%2C%20it%20is%20included.%20Lastly%2C%20if%20a%20path%20is%20prefixed%20with%20%2B%2C%20it%20forces%20inclusion%20of%20the%20path%2C%20which%20is%20useful%20for%20paths%20excluded%20at%20the%20schema%20level.)

### 題目（將答案寫在 GitHub 並提交至回報區）
- 實做登入功能 POST `/users/sign_in`，使用 bcryptjs `compare()` 比對密碼是否與資料庫中的密碼符合，並根據結果回饋訊息，若符合則需產生 JWT 給 client
- 若找不到符合的使用者資料或密碼比對不正確，都需回饋錯誤訊息
- 將產生 JWT 功能拆出獨立模組

::: spoiler 回饋訊息範例

![](https://i.imgur.com/GAWJkNu.png)

![](https://i.imgur.com/EHmLduK.png)

![](https://i.imgur.com/VXAYd2G.png)
:::



回報流程
---
請同學依照下圖教學觀看解答、回報答案:

![](https://i.imgur.com/QtL8zEW.png)

回報格式：請在「回報區」貼上 CodePen 或 HackMD 連結回報答案 (為了統計人數，請同學依序加上「報數」)


<!-- 解答
範例參考 https://github.com/gonsakon/express-week4-sample/blob/week6/routes/users.js


```javascript

const generateSendJWT= (user,statusCode,res)=>{
  // 產生 JWT token
  const token = jwt.sign({id:user._id},process.env.JWT_SECRET,{
    expiresIn: process.env.JWT_EXPIRES_DAY
  });
  user.password = undefined;
  res.status(statusCode).json({
    status: 'success',
    user:{
      token,
      name: user.name
    }
  });
}

router.post('/sign_in', handleErrorAsync(async(req,res,next)=>{
  const { email, password } = req.body;
  if (!email || !password) {
    return next(appError( 400,'帳號密碼不可為空',next));
  }
  const user = await User.findOne({ email }).select('+password');
  console.log(user);
  if (!user) {
    return next(appError(400, "帳號或密碼錯誤，請重新輸入！", next));
  }
  const auth = await bcrypt.compare(password, user.password);
  if(!auth){
    return next(appError(400,'您的密碼不正確',next));
  }
  generateSendJWT(user,200,res);
}))
```

-->

回報區
---

| 報數 | 組別 / 名字       | codepen / hackMD / 其他回饋                                   |
| ---- | ----------------- | ------------------------------------------------------------- |
| 1    | 第五組 / Hazel    | [HackMD@Hazel](https://hackmd.io/@hazelwu/day29)              |
| 2    | 第 14 組｜East    | [HackMD](https://hackmd.io/_WD3A3xiSraObPxhV-Q9sw)            |
| 3    | 第 11 組｜Han Lai | [HackMD](https://hackmd.io/61g9Dmb5T2uuMj6rD4hTwQ?view)       |
| 4    | 第 3 組｜hiYifang | [HackMD](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/S1WEL_yPc) |
| 5    | 第 9 組 / 黃士桓  | [HackMD](https://hackmd.io/UvlyqWbuQdyJLLOrnPacYw)            |
| 6    | 第 4 組 / 苡安    | [HackMD](https://hackmd.io/vLg0fTZxQkWzuvmq7mlslA)            |
| 7   |第 9 組 / konstante |[HackMD](https://hackmd.io/5m9D1IUAQeusv5Qh2HJbvg?edit)                                                               |
| 8    | 第 4 組 / 小宥    | [HackMD](https://hackmd.io/il1PRjCHQQ-VeVbwzArOWw)            |
| 9    | 第 3 組 / Hobby    | [HackMD](https://hackmd.io/@hobbyling/day29)            |
| 10    | 第 2 組 / joe    | [HackMD](https://hackmd.io/uaRTw9c0TgOrADyXMmGL0Q?view#519-jwt-sign_in)   
| 11    | 第 7 組 / jason06286    | [HackMD](https://hackmd.io/xIetQwQnSs2xYaI_znvvog)  |
| 12    | 第 12 組 / Jimmy    | [HackMD](https://hackmd.io/1T7VCdBKR9iWXCTMWKp1zA)  |
| 13 | 第2組 / wendy | [HackMD](https://hackmd.io/80FIwll1QUa4u0-WoBv-hQ#20220518)|
| 14 | 第16組 / 皓皓 | [HackMD](https://hackmd.io/@cutecat8110/SkQPzcKcc)|
