# 🏅 Day 30 - bcrypt.js 密碼加解密 ### 密碼加密 使用 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) 題目 --- 延續前一天 Day29 解答,運用 bcrypt.js 將使用者註冊輸入的密碼加密後再新增至 User 內 ```javascript= router.post('/sign_up', handleErrorAsync(async (req, res, next) => { let { name, email, password } = req.body; // 加入驗證,確保使用者註冊資料符合格式 // 三個欄位皆必填 if (!name || !email || !password) { return next(appError(400, '請確保所有欄位皆填寫', next)); } // 暱稱 name 長度需至少 2 個字元以上 if (!validator.isLength(name, { min: 2 })) { return next(appError(400, '暱稱需至少 2 個字元以上', next)); } // 信箱 email 格式正確 if (!validator.isEmail(email)) { return next(appError(400, 'Email 格式錯誤', next)); } // 密碼 password 長度至少 8 碼以上 if (!validator.isLength(password, { min: 8 })) { return next(appError(400, '密碼需至少 8 碼以上', next)); } // 將密碼 password 加密 ... const newUser = await User.create({ email, password, name }); res.status(200).json({ status: 'success', data: newUser }); })); ``` ## 回報流程 將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔! 解答位置請參考下圖(需打開程式碼的部分觀看) ![](https://i.imgur.com/vftL5i0.png) <!-- 解答: ```javascript= router.post('/sign_up', handleErrorAsync(async (req, res, next) => { let { name, email, password } = req.body; // 加入驗證,確保使用者註冊資料符合格式 // 三個欄位皆必填 if (!name || !email || !password) { return next(appError(400, '請確保所有欄位皆填寫', next)); } // 暱稱 name 長度需至少 2 個字元以上 if (!validator.isLength(name, { min: 2 })) { return next(appError(400, '暱稱需至少 2 個字元以上', next)); } // 信箱 email 格式正確 if (!validator.isEmail(email)) { return next(appError(400, 'Email 格式錯誤', next)); } // 密碼 password 長度至少 8 碼以上 if (!validator.isLength(password, { min: 8 })) { return next(appError(400, '密碼需至少 8 碼以上', next)); } // 將密碼 password 加密 password = await bcrypt.hash(password, 12); const newUser = await User.create({ email, password, name }); res.status(200).json({ status: 'success', data: newUser }); })); ``` --> 回報區 --- <!-- 將答案貼至下方表格內,格式: | Discord 暱稱 | [CodePen](連結) | --> | Discord | CodePen / 答案 | |:-------------:|:-----------------:| | Tau | [CodePen](https://codepen.io/Tau-Hsu/pen/EaxKXNe?editors=0010) | |janetlai|[CodePen](https://codepen.io/eiddkqxz-the-builder/pen/bNGpRrg?editors=1112) |helena|[CodePen](https://codepen.io/helena27/pen/NPWNvmo) | poyi | [CodePen](https://codepen.io/poyi-the-flexboxer/pen/YPzqpxO?editors=1010) | |daffytseng| [CodePen](https://codepen.io/Daffy-Tseng/pen/zxYqRWz)| |adengg| [CodePen](https://codepen.io/Osases/pen/JojXZLM?editors=0010)| |bian_yang_mofa| [CodePen](https://codepen.io/cssf998811/pen/RNwamzd?editors=0010)| |hannahpun| [CodePen](https://codepen.io/hannahpun/pen/EaxyWJV?editors=0010)| |JC| [CodePen](https://codepen.io/lifetimingwhisper/pen/VYwKMXM)| |HarryKuo|[CodePen](https://codepen.io/harry_kuo/pen/VYwmzjO?editors=0010)| |sui_hsilan|[CodePen](https://codepen.io/suihsilan/pen/YPzZyzV?editors=0010)| | hsin yu |[CodePen](https://codepen.io/tina2793778/pen/XJWaWaG)| |ZoeKang|[CodePen](https://codepen.io/byehywmx-the-animator/pen/ByaZXpO)