---
tags: Node.js 直播班 - 2022 春季班
---
# 🏅 Day 28
## JWT 產生身份驗證 token
[JWT 流程圖](https://whimsical.com/jwt-UKUY1rj1vfoN6uyic7e4Sm)

當使用者登入或註冊,後端經過驗證後確認資料格式正確,就會產生一組的 token 回傳至使用者(client 端),此 token 用於身份驗證,接下來 client 端造訪需權限的頁面、發送需要權限的請求,若未帶上此 token 或是 token 驗證錯誤,都會請求失敗
接下來會使用 jsonwebtoken(JWT) 套件中的 `sign()` 實作產生 token 的流程(流程圖步驟 2)
```javascript
const jwt = require('jsonwebtoken');
jwt.sign(payload, secretOrPrivateKey, \[options, callback\])
```
- payload 會是一個物件,為該使用者的相關資訊(如 id)
- secretOrPrivateKey 私鑰可以是字串、buffer 或物件,這裡會加入一段字串(如:`secret`)並設定為環境變數 `process.env.JWT_SECRET`
- options 或 callback 函式,options 為一個物件,可根據文件中有提供的選項客製化,例如:設定此 token 的到期日
```javascript
const token = jwt.sign({id:id},process.env.JWT_SECRET,{
expiresIn: process.env.JWT_EXPIRES_DAY
});
```
產生出的 token 會以 . 分隔,其中第一二段的 header 及 payload 都是可以透過 base64 編碼得知內容的
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. # header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9. # payload
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ # signature
```
### 參考資源
[jwt.sign()](https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback)
[什麼是 JWT](https://5xruby.tw/posts/what-is-jwt)
### 題目(將答案寫在 並提交至回報區)
延續前一天的每日任務,優化註冊功能,當使用者的資料都通過自訂的驗證條件,並成功新增使用者資料後,使用 `jwt.sign()` 產生 JWT,並回傳給 client(回傳內容須包含 token、使用者名稱 name)
回傳範例

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

回報格式:請在「回報區」貼上 CodePen 或 HackMD 連結回報答案 (為了統計人數,請同學依序加上「報數」)
<!-- 解答
```javascript
範例參考 https://github.com/gonsakon/express-week4-sample/blob/week6/routes/users.js
router.post('/sign_up', handleErrorAsync(async(req, res, next) =>{
let { email, password, confirmPassword, name } = req.body;
// 內容不可為空
if(!email||!password||!confirmPassword||!name){
return next(appError("400","欄位未填寫正確!",next));
}
// 密碼正確
if(password!==confirmPassword){
return next(appError("400","密碼不一致!",next));
}
// 密碼 8 碼以上
if(!validator.isLength(password,{min:8})){
return next(appError("400","密碼字數低於 8 碼",next));
}
// 是否為 Email
if(!validator.isEmail(email)){
return next(appError("400","Email 格式不正確",next));
}
// 加密密碼
password = await bcrypt.hash(password,12);
const newUser = await User.create({
email,
password,
name
});
// 產生 JWT
const token = jwt.sign({id:newUser._id},process.env.JWT_SECRET,{
expiresIn: process.env.JWT_EXPIRES_DAY
});
// 將 token 回傳至 client
res.status(200).json({
status: 'success',
user:{
token,
name: newUser.name
}
});
}))
```
-->
回報區
---
| 報數 | 組別 / 名字 | codepen / hackMD / 其他回饋 | |
| ---- | ------------------- | --------------------------------------------------------------- | --- |
| 1 | 第 2 組 / joe | [HackMD](https://hackmd.io/uaRTw9c0TgOrADyXMmGL0Q?view#517-jwt) | |
| 2 | 第 11 組 / Han Lai | [HackMD](https://hackmd.io/keZFagTcTjC6sNifERvalg?view) | |
| 3 | 第 14 組|East | [HackMD](https://hackmd.io/rNAa3hLXTb2tNmhuu4fN7Q) | |
| 4 | 第 9 組 / 黃士桓 | [HackMD](https://hackmd.io/wbFaGdQhSsqLwJoicbqj-A) | |
| 5 | 第 3 組 / hiYifang | [HackMD](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/S1WEL_yPc) | |
| 6 | 第 4 組 / 苡安 | [HackMD](https://hackmd.io/CfH_TdVGQsOX711xonhdzQ) | |
|7 | 第 9 組 / konstante |[HackMD](https://hackmd.io/zOBayYeYTK-RilechiS0-A?edit) | |
|8 | 第 5 組 @ Hazel |[HackMD@Hazel](https://hackmd.io/@hazelwu/day28) |
|9 | 第 4 組 / 小宥 |[HackMD](https://hackmd.io/JUH9rOUeTyWorfUHxUYbIw) |
|10 | 第 3 組 / Hobby |[HackMD](https://hackmd.io/@hobbyling/day28) |
|11 | 第 7 組 / jason06286 |[HackMD](https://hackmd.io/e27JAhkRTUmFwLsq0H1OTQ) |
|12 | 第 12 組 / Jimmy |[HackMD](https://hackmd.io/BcvJoQnvQTSWjrMCDHqmKg) |
|13 | 第 2 組 / wendy | [HackMD](https://hackmd.io/80FIwll1QUa4u0-WoBv-hQ#20220517)|
|14 | 第 16 組 / 皓皓 | [HackMD](https://hackmd.io/@cutecat8110/HkhBAKFc9)|