# 【Day 26】bcrypt.js 密碼加解密 ## :herb: <font color="#E58638">講義內容</font> **密碼加密** 使用 bcrypt.js 的 `hash()` 以非同步的方式將密碼加密 ```javascript bcrypt.hash(password,12); // 第一個參數是要做雜湊加密的字串,第二個參數是要加鹽的字串長度 ``` 補充: [雜湊(Hash function)](https://zh.wikipedia.org/zh-tw/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8)為一種演算法,會將資料打亂建立雜湊值,雜湊值具有「不可逆」的性質(由此值回推原本的值非常困難),因此常用於密碼加密 [鹽(Salt)](https://zh.wikipedia.org/zh-tw/%E7%9B%90_(%E5%AF%86%E7%A0%81%E5%AD%A6))在密碼學中,是指在雜湊之前將雜湊內容(例如:密碼)的任意固定位置插入特定的字串。這個在雜湊中加入字串的方式稱為「加鹽」 **密碼解密** 密碼加密後,未來需要驗證是否為該註冊帳號就需以 `compare()` 將密碼與加密後的字串進行比對 ```javascript bcrypt.compare(password, user.password); // 第一個參數是接收到的密碼,第二個參數是由資料庫找出的該 user 的密碼,為雜湊加密的字串 ``` ### 參考資源 [bcrypt.js - hash](https://github.com/dcodeIO/bcrypt.js#hashs-salt-callback-progresscallback) [bcryptjs - compare](https://github.com/dcodeIO/bcrypt.js#compares-hash-callback-progresscallback) ### 題目(將答案寫在 GitHub 並提交至回報區) 測試註冊功能 POST `/users/sign_up`,使用[第五週專案](https://github.com/gonsakon/express-week4-sample/tree/week5) 練習(接下來會以此專案陸續練習第六週的內容) - 於 models/user.js 加入使用者資料 schema,以儲存使用者 email 暱稱 密碼(可參考第六週[範例](https://github.com/gonsakon/express-week4-sample/blob/week6/models/usersModel.js)) - 安裝 [bcryptjs](https://www.npmjs.com/package/bcryptjs) 套件,使用 bcrypt.js 的 `hash()` 將 client 端傳送的密碼經過雜湊再儲存至資料庫 ```javascript router.post('/sign_up', handleErrorAsync(async(req, res, next) =>{ let { email, password, confirmPassword, name } = req.body; // 加密密碼 password = const newUser = await User.create({ email, password, name }); res.status(200).json({ status: 'success', data: newUser }); })) ``` 測試註冊 API `/users/sign_up` 並取得加密後的密碼 範例 ![](https://i.imgur.com/iVkplJW.png =500x) --- ## :herb: <font color="#E58638">作業回報</font> - [Github](https://github.com/hobbyling/metawall-backend/blob/main/controllers/userController.js) - 註冊 API ```javascript // 註冊 async signUp(req, res, next) { let { name, email, password, confirmPassword } = req.body // 內容不可為空 if (!name || !email || !password || !confirmPassword) { 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)) } // Email 是否已被註冊過 // 先在資料庫尋找是否已存在 email const isRegister = await User.findOne({ email }).count() if (isRegister === 0) { // 密碼加密 password = await bcrypt.hash(password, 12) const newUser = await User.create({ name, email, password }) generateSendJWT(newUser, 201, res) } else { return next(appError(400, '此 Email 已註冊過', next)) } }, ``` - Postman 實際操作 ![Postman 實際操作](https://i.imgur.com/cnqn4u4.png) --- ###### tags: `Node.js 直播班 - 2022 春季班`