dev-resources.site
for different kinds of informations.
วิธีทำ Auth API ด้วย Express, JWT, MySQL และ Prisma
Published at
12/24/2024
Categories
express
mysql
prisma
jwt
Author
xnewz
Author
5 person written this
xnewz
open
การสร้าง Auth API ด้วย JWT และ MySQL โดยใช้ Prisma สำหรับการจัดการฐานข้อมูล
จะมีการแยกส่วนประกอบออกเป็นไฟล์ต่างๆ เพื่อความสะดวกในการแก้ไข
โดยในตัวอย่างนี้ เราจะใช้ Node.js กับ Express.js สำหรับ backend และ JWT สำหรับการจัดการ token
พร้อมด้วย Prisma สำหรับการจัดการกับฐานข้อมูล MySQL
ขั้นตอนการติดตั้งและตั้งค่า
mkdir auth-api
cd auth-api
สร้างโปรเจค Node.js และติดตั้ง package ที่ใช้
npm init -y
npm install express prisma @prisma/client jsonwebtoken bcryptjs body-parser
ตั้งค่า Prisma
npx prisma init
ตั้งค่าไฟล์ Prisma schema
- prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
username String @unique
password String
}
ตั้งค่าไฟล์ .env
-
user
ชื่อผู้ใช้ของ MySQL -
password
รหัสผ่านของ MySQL -
localhost:3306
ที่อยู่ของ MySQL -
auth_db
ชื่อฐานข้อมูลที่จะใช้
DATABASE_URL="mysql://user:password@localhost:3306/auth_db"
สร้างฐานข้อมูลและตาราง
npx prisma migrate dev --name init
สร้างไฟล์และโฟลเดอร์ต่างๆ
touch server.js config.js routes.js
mkdir controllers models middlewares
touch controllers/authController.js middlewares/middleware.js
โครงสร้างโปรเจค
auth-api/
├── controllers/
│ └── authController.js
├── middlewares/
│ └── middleware.js
├── models/
│ └── userModel.js
├── prisma/
│ ├── migrations/
│ │ └── <migration files>
│ ├── schema.prisma
├── .env
├── config.js
├── package.json
├── routes.js
├── server.js
เขียนโค้ดสำหรับแต่ละไฟล์
- server.js
const express = require('express'); // เรียกใช้งาน express เพื่อสร้าง server
const bodyParser = require('body-parser'); // เรียกใช้งาน body-parser เพื่อแปลงข้อมูลที่ส่งมาให้เป็น JSON
const routes = require('./routes'); // เรียกใช้งานไฟล์ routes.js ที่เราสร้างไว้เพื่อใช้ในการกำหนดเส้นทางของ API
const app = express(); // สร้าง instance ของ express
const PORT = process.env.PORT || 3000; // กำหนด port ที่จะใช้ในการรัน server
app.use(bodyParser.json()); // ใช้ body-parser ในการแปลงข้อมูลที่ส่งมาให้เป็น JSON
app.use('/api', routes); // กำหนดเส้นทางของ API
app.listen(PORT, () => { // รัน server ที่ port ที่กำหนด
console.log(`Server is running on port ${PORT}`);
});
- config.js
module.exports = {
jwtSecret: 'your-secret-key' // กำหนด secret key สำหรับการสร้าง token
};
- models/userModel.js
const { PrismaClient } = require('@prisma/client'); // เรียกใช้งาน PrismaClient จาก @prisma/client
const prisma = new PrismaClient(); // สร้าง instance ของ PrismaClient
const bcrypt = require('bcryptjs'); // เรียกใช้งาน bcryptjs เพื่อใช้ในการเข้ารหัสรหัสผ่าน
// สร้างผู้ใช้ใหม่
const createUser = async (user) => {
// เข้ารหัสรหัสผ่านก่อนที่จะเก็บไว้ในฐานข้อมูล
const hash = await bcrypt.hash(user.password, 10);
// บันทึกข้อมูลผู้ใช้ลงในฐานข้อมูล
return prisma.user.create({
data: {
username: user.username,
password: hash
}
});
};
// ค้นหาผู้ใช้จากชื่อผู้ใช้
const findUserByUsername = async (username) => {
return prisma.user.findUnique({
where: { username: username }
});
};
module.exports = {
createUser,
findUserByUsername
};
- controllers/authController.js
const jwt = require('jsonwebtoken'); // เรียกใช้งาน jwt เพื่อใช้ในการสร้าง token
const bcrypt = require('bcryptjs'); // เรียกใช้งาน bcryptjs เพื่อใช้ในการเข้ารหัสรหัสผ่าน
const config = require('../config'); // เรียกใช้งานไฟล์ config.js ที่เราสร้างไว้
const User = require('../models/userModel'); // เรียกใช้งาน userModel.js ที่เราสร้างไว้
const register = async (req, res) => {
const { username, password } = req.body; // รับข้อมูล username และ password จาก body ของ request
// สร้างผู้ใช้ใหม่
try {
await User.createUser({ username, password });
res.status(201).json({ message: 'User registered successfully' });
} catch (err) { // หากเกิดข้อผิดพลาดในการสร้างผู้ใช้
res.status(500).json({ message: 'Error registering user' });
}
};
const login = async (req, res) => {
const { username, password } = req.body; // รับข้อมูล username และ password จาก body ของ request
try {
const user = await User.findUserByUsername(username); // ค้นหาผู้ใช้จากชื่อผู้ใช้
if (!user) { // หากไม่พบผู้ใช้
return res.status(401).json({ message: 'Invalid username or password' });
}
// หากรหัสผ่านไม่ตรงกับที่เก็บไว้ในฐานข้อมูล
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ message: 'Invalid username or password' });
}
// สร้าง token และส่งกลับไปให้ผู้ใช้
const token = jwt.sign({ id: user.id }, config.jwtSecret, { expiresIn: '1h' });
res.json({ token });
} catch (err) { // หากเกิดข้อผิดพลาดในการเข้าสู่ระบบ
res.status(500).json({ message: 'Error logging in' });
}
};
module.exports = {
register,
login
};
- middlewares/middleware.js
const jwt = require('jsonwebtoken'); // เรียกใช้งาน jwt เพื่อใช้ในการตรวจสอบ token
const config = require('../config'); // เรียกใช้งานไฟล์ config.js ที่เราสร้างไว้
// next คือ callback function ที่ใช้ในการส่งต่อไปยัง middleware ถัดไป
const verifyToken = (req, res, next) => { // middleware สำหรับตรวจสอบ token
const token = req.headers['authorization']; // รับ token จาก header ของ request
if (!token) return res.status(403).json({ message: 'No token provided' }); // หากไม่มี token ให้ส่งข้อความกลับไปว่าไม่มี token
jwt.verify(token, config.jwtSecret, (err, decoded) => { // ตรวจสอบ token
if (err) return res.status(500).json({ message: 'Failed to authenticate token' }); // หากไม่สามารถตรวจสอบ token ได้ให้ส่งข้อความกลับไปว่าไม่สามารถตรวจสอบ token ได้
req.userId = decoded.id; // ถ้าตรวจสอบ token สำเร็จ ให้เก็บ id ของผู้ใช้ไว้ใน req.userId
next(); // ส่งต่อไปยัง middleware ถัดไป
});
};
module.exports = {
verifyToken
};
- routes.js
const express = require('express'); // เรียกใช้งาน express
const authController = require('./controllers/authController'); // เรียกใช้งาน authController.js ที่เราสร้างไว้
const middleware = require('./middlewares/middleware'); // เรียกใช้งาน middleware.js ที่เราสร้างไว้
const router = express.Router(); // สร้าง instance ของ express.Router
router.post('/register', authController.register); // สร้างเส้นทางสำหรับการลงทะเบียนผู้ใช้
router.post('/login', authController.login); // สร้างเส้นทางสำหรับการเข้าสู่ระบบ
// Protected route example
router.get('/protected', middleware.verifyToken, (req, res) => { // สร้างเส้นทางสำหรับการตรวจสอบ token
res.json({ message: 'This is a protected route', userId: req.userId }); // ส่งข้อความกลับไปว่านี่คือเส้นทางที่ถูกป้องกัน
});
module.exports = router;
รัน server
node server.js
เราสามารถทดสอบ API ด้วย Postman หรือ Thunder Client โดยการสร้าง request ไปที่ http://localhost:3000/api/register
และ http://localhost:3000/api/login
และส่งข้อมูล username และ password ไปด้วย
ตัวอย่าง request สำหรับ route register
- /api/register
{
"username": "john_doe",
"password": "password123"
}
- Response
{
"message": "User registered successfully"
}
ตัวอย่าง request สำหรับ route login
- /api/login
{
"username": "john_doe",
"password": "password123"
}
- Response
{
"token": "token-string"
}
ตัวอย่าง request สำหรับ route protected
- /api/protected
// ใส่ token ใน header ของ request
{
"Authorization": "token-string"
}
- Response
{
"message": "This is a protected route",
"userId": 1
}
นอกจากนี้เรายังสามารถใช้งาน Prisma Studio เพื่อดูข้อมูลในฐานข้อมูลได้ด้วย
npx prisma studio
สามารถดูตัวอย่างโค้ดทั้งหมดได้จาก GitHub
หรือสามารถดูตัวอย่างการทำงานได้จาก YouTube
jwt Article's
30 articles in total
Testing with JWT in .NET APIs
read article
JWT Authentication With NodeJS
read article
[Part 1] Rails 8 Authentication but with JWT
read article
How to Generate a Secure JWT Secret Using Node.js
read article
Implementing JWT Authentication in .NET API
read article
Managing JWT Logout with Blacklists and Redis: A Beginner-Friendly Guide
read article
Understanding the Differences Between OAuth2 and OpenID Connect (OIDC)
read article
JWT vs Opaque Tokens: A Comprehensive Guide to Choosing Wisely
read article
วิธีทำ Auth API ด้วย Express, JWT, MySQL และ Prisma
currently reading
JsonWebTokenError: jwt must be provided
read article
JSON Web Tokens (JWT): Guía Esencial y Buenas Prácticas
read article
Djoser+SimpleJWT
read article
Mastering JWT Authentication: A Complete Guide with MERN Stack
read article
How to secure minimal api microservices with asp.net core identity
read article
PHP HyperF -> Firebase JWT
read article
How to Create a quick Authentication library for NestJS/MongoDB application
read article
Learning JWT security using KumuluzEE — The finances of a league of the environment
read article
Feijuca.Auth - Part 1: Configuring the tool
read article
Securing Your .NET APIs with JWT Authentication
read article
"Unauthorized: No token provided")
read article
Implementing JWT Authentication in Express API
read article
Integration of Salesforce, Node.js, and React: A Step-by-Step Guide
read article
Definition of Jwt and Use
read article
Implementing JWT Authentication in Go API
read article
flow design for access and refresh token- JWT
read article
Implementing JWT Authentication in Spring Boot API
read article
What is REST Api ? Implement and Secure ?
read article
Securing a REST API with JWT Authentication in C# Using AES-Encrypted Keys
read article
MS Graph API Certificate and Client Secret OAuth2.0 in Java Spring boot
read article
Securing Your Fullstack App: Authentication & Authorization with JWT in Next.js and Node 🔒 🚀
read article
Featured ones: