Bcrypt คือ password hashing function ที่สร้างขึ้นจากพื้นฐานของ Blowfish cipher เป็นการเข้ารหัสแบบทางเดียว
โดยปกติการเข้ารหัสมี 2 แบบ คือ การเข้ารหัสแบบที่สามารถถอดรหัสข้อมูลกลับออกมาได้ และการเข้ารหัสแบบทางเดียวที่ไม่สามารถถอดรหัสข้อมูลกลับออกมาได้ เช่น hashing function
เริ่มต้นสร้าง Project
ในการจะเริ่มใช้งาน Bcrypt หากใครที่ยังเคยได้ติดตั้ง Node.js และยังไม่เคยใช้งาน Express.js มาก่อนแนะนำว่าให้ลองอ่านบทความนี้ก่อนจะช่วยได้มากเลย https://www.borntodev.com/2023/11/04/express-js-คืออะไร/
ในการเริ่มต้นสร้าง Project ใหม่ ให้ทุกคนสร้าง Folder เปล่าขึ้นมาใหม่ และเปิด terminal ขึ้นมาพร้อมกับรันคำสั่งต่อไปนี้เพื่อเป็นการสร้าง Project
$ npm init -y
เมื่อรันคำสั่งเสร็จเรียบร้อยแล้ว เราจะได้ package.json มาหนึ่งไฟล์ หลังจากนั้นเราสามารถติดตั้ง Library ต่างๆ ที่จำเป็นสำหรับการทดลองใช้งาน Bcrypt อย่างง่ายกันด้วยคำสั่งต่อไปนี้
$ npm install bcrypt express
เมื่อรันคำสั่งเสร็จเรียบร้อยแล้ว เมื่อเราเข้าไปดูใน package.json จะเห็นว่ามี dependencies เพิ่มเข้ามา เป็น bcrypt และ express ถือว่าติตตั้งได้เรียบร้อย
ติดตั้ง Bcrypt และ Express ใน index.js ให้เรียบร้อยด้วย Code ต่อไปนี้
const express = require('express')
const bcrypt = require('bcrypt')
const app = express()
const port = 3000
const users = []
app.use(express.json())
JavaScriptสร้าง API สำหรับ Register & Login
ใน Project นี้เพื่อความง่ายเราจะไม่ต่อฐานข้อมูลนะครับ แต่จะใช้เป็น Array ในการเก็บข้อมูลเบื้องต้น โดยการทำ API สำหรับ Register นั้นเราต้องคำนึกถึงอะไรบ้าง
- จะรับข้อมูลอะไรเข้ามาบ้าง ในที่นี้จะเป็น email และ password
- การตรวจสอบความถูกต้องของข้อมูล โดยต้องการให้ email อยู่ใน format (test@gmail.com) และต้องไม่มี email ซ้ำในระบบ
- การจัดเก็บ password เพื่อความปลอดภัยเราจะไม่เก็บข้อมูลเป็น password ดิบๆ แต่จะเก็บ password ในรูปแบบที่ผ่านการ hash แล้วเพื่อการนำไปเปรียบเทียบเท่านั้น
app.post('/register', (req, res) => {
const user = {
email: req.body.email,
password: req.body.password
}
// Vailidate the email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(user.email)) {
return res.status(400).json({
message: 'Invalid email format'
})
}
// Vailidate the email no duplicates
const duplicate = users.find((u) => u.email === user.email)
if (duplicate) {
return res.status(409).json({
message: 'Email already exists'
})
}
// Hash the password
bcrypt.hash(user.password, 10, (err, hash) => {
if (err) {
console.error('Error hashing password:', err)
return
} else {
user.password = hash
users.push(user)
return res.status(201).json({
message: 'User created'
})
}
})
})
JavaScriptต่อมาสิ่งที่เราจะต้องคำนึงถึงในการสร้าง API Login มีดังนี้ครับ
- จะรับข้อมูลอะไรเข้ามาบ้าง ในที่นี้จะเป็น email และ password เหมือนกับ Register
- เราต้องตรวจสอบให้แน่ในว่า email ที่รับมามีอยู่ในระบบแล้วจริงๆ
- ทำการเปรียบเทียบ password ที่รับมากับ hash password ที่อยู่ในระบบ
- ทำการ Handling error ต่างๆ ให้เรียบร้อย
app.post('/login', (req, res) => {
const { email, password } = req.body
const user = users.find((u) => u.email === email)
if (!user) {
return res.status(401).json({
message: 'Invalid email or password'
})
}
bcrypt.compare(password, user.password, (err, result) => {
if (err) {
console.error('Error comparing password:', err)
return
}
if (result) {
return res.status(200).json({
message: 'Login successful'
})
} else {
return res.status(401).json({
message: 'Invalid email or password'
})
}
})
})
JavaScriptต่อมาเป็น API สำหรับการดูข้อมูลในระบบของเราอย่างง่ายนะครับ ***คำเตือนไม่ควรทำแบบนี้ในงานจริง
app.get('/users', (req, res) => {
res.json({
users
})
})
JavaScriptหลังจากนั้นสร้าง HTTP Server ด้วย Express
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
JavaScriptทดสอบการทำงานของระบบ Register & Login
ในการทดสอบการทำงานของ API เราจะใช้ Postman มาช่วย โดยสามารถดาวน์โหลดได้จากลิ้งนี้ https://www.postman.com/downloads/
หลังจาก Sign in เข้า Postman มาเรียบร้อยให้ลองส่งข้อมูลผ่าน API Register ดังรูป
จะได้ผลลัพธ์ดังภาพต่อมา
เมื่อลองดูข้อมูลจาก API users จะได้ผลลัพธ์เป็นภาพต่อไปนี้
จะเห็นได้ว่า password จะไม่ใช่ 123456 ตามที่เราส่งข้อมูลไปแต่จะเป็นการเก็บ password ที่ผ่านการ hash มาแล้ว
ต่อมาเรามาลอง API Login กันดีกว่าหากว่าใส่ข้อมูลถูกต้องก็จะแสดงผลได้ดังรูปต่อไปนี้