Section 6

ความปลอดภัย + ทบทวนภาพรวม
Part 1 — ความปลอดภัยที่ต้องรู้
🗺️ ตำแหน่งตอนนี้ในระบบ
- ✅ เตรียมเครื่องมือ (ทำไปแล้ว)
- ✅ Angular (frontend) (ทำไปแล้ว)
- 🟢 NestJS (backend) ← กำลังทำส่วนนี้
- ✅ PostgreSQL (ฐานข้อมูล) (ทำไปแล้ว)
ต่อไป: เก็บรายละเอียดปลีกย่อยให้เว็บพร้อมใช้งานจริง
1.1 ทดลองโจมตีเว็บของตัวเอง
เปิด localhost:4200/books/new แล้วกรอกชื่อหนังสือว่า
<script>alert('ถูกแฮกแล้ว')</script>
กดบันทึก แล้วดูหน้ารายการ
✅ ต้องเห็นเป็นข้อความธรรมดา ไม่มีกล่องเด้ง

💡 การโจมตีแบบนี้เรียกว่า XSS — คือการแอบฝังโค้ดลงในช่องกรอกข้อมูล หวังให้เว็บเอาไปรันจริง ถ้าสำเร็จ ผู้โจมตีจะขโมยข้อมูลผู้ใช้คนอื่นได้
Angular ป้องกันให้อัตโนมัติ เวลาแสดงค่าด้วย
{{ }}Angular จะแปลงเป็นข้อความธรรมดาเสมอ ไม่ประมวลผลเป็นโค้ด⚠️ แต่ถ้าไปใช้คำสั่งอย่าง
innerHTMLเองจะไม่ปลอดภัย — อย่าใช้ถ้าไม่จำเป็นจริง ๆ
ลบหนังสือเล่มนี้ทิ้งก่อนไปต่อ
1.2 ทำไม Prisma ถึงสำคัญกว่าที่คิด
สมมติเราไม่ใช้ Prisma แต่ต่อ SQL เป็นข้อความเองแบบนี้
// ❌ อันตราย ห้ามเขียนแบบนี้เด็ดขาด
const sql = "SELECT * FROM Book WHERE title = '" + keyword + "'";
ถ้าผู้ใช้พิมพ์คำค้นว่า ' OR '1'='1 ประโยคจะกลายเป็น
SELECT * FROM Book WHERE title = '' OR '1'='1'
ซึ่งเป็นจริงเสมอ ทำให้ได้ข้อมูลทั้งตารางออกมา และถ้าพิมพ์ซับซ้อนกว่านี้ก็ลบทั้งตารางได้
💡 เรียกว่า SQL Injection เป็นช่องโหว่ (vulnerability) ที่ทำให้ระบบใหญ่ ๆ ล่มมาแล้วนับไม่ถ้วน
Prisma ป้องกันให้โดยอัตโนมัติ เพราะเราไม่ได้ต่อข้อความเอง แต่ส่งค่าแยกไปให้ฐานข้อมูลจัดการ ฐานข้อมูลจึงมองค่านั้นเป็น "ข้อมูล" เสมอ ไม่ใช่ "คำสั่ง"
นี่คือเหตุผลสำคัญข้อหนึ่งที่โลกจริงใช้ ORM
1.3 ตรวจว่าความลับไม่หลุด
เปิดโฟลเดอร์ apps/api ดูให้แน่ใจว่าไฟล์ .env อยู่ตรงนั้นที่เดียว
❌ หากคัดลอกไฟล์นี้ไปไว้ที่อื่นโดยไม่ตั้งใจ (เช่น ส่งให้เพื่อนช่วยดูโค้ด หรือแนบไปกับข้อความ) ให้ลบทิ้งจากที่นั้นทันที
⚠️ ทำไมเรื่องนี้สำคัญ หากมีผู้ส่งไฟล์นี้ให้ผู้อื่นโดยไม่ตั้งใจ เท่ากับแนบรหัสผ่านฐานข้อมูลไปให้ผู้อื่นเห็นด้วย
จากนั้นเปิด localhost:4200 กด F12 → แท็บ Sources แล้วเปิดดูไฟล์โค้ดของเรา
💡 สังเกตว่าโค้ด Angular ทั้งหมดอ่านได้หมด — ทุกคนที่เข้าเว็บเราเห็นสิ่งนี้ได้
นี่คือคำตอบของคำถามตั้งแต่ Section แรก ว่าทำไม frontend ต่อฐานข้อมูลตรง ๆ ไม่ได้ ถ้าเอา connection string ไปไว้ฝั่ง Angular เท่ากับแปะรหัสผ่านฐานข้อมูลไว้ให้คนทั้งโลกอ่าน
ส่วนโค้ดฝั่ง NestJS รันอยู่บนเซิร์ฟเวอร์ ผู้ใช้เห็นแค่ผลลัพธ์ JSON เท่านั้น ความลับจึงอยู่ฝั่งนั้นได้
1.4 ทดสอบว่า API ตรวจข้อมูลจริงไหม
ปิดหน้าเว็บไป แล้วยิงตรงไปที่ API ด้วย PowerShell
curl.exe -X POST http://localhost:3000/api/books -H "Content-Type: application/json" -d "{\"title\":\"\",\"author\":\"x\",\"year\":2020,\"categoryId\":1}"
✅ ต้องได้ error กลับมาว่า "กรุณากรอกชื่อหนังสือ"
💡 นี่คือเหตุผลที่ต้องตรวจสองชั้น การตรวจฝั่ง Angular มีไว้ให้ผู้ใช้รู้ตัวเร็ว แต่ป้องกันอะไรไม่ได้เลย เพราะคนที่ตั้งใจโกงข้ามหน้าเว็บมายิง API ตรง ๆ แบบที่เราเพิ่งทำได้
การตรวจที่ป้องกันได้จริงคือฝั่ง API เท่านั้น
1.5 ทดสอบ API ด้วย Postman (ทางเลือกแทน PowerShell)
curl.exe ใช้ได้ผลดี แต่พิมพ์ JSON ยาว ๆ ใน PowerShell ต้องคอย escape เครื่องหมายคำพูดจนอ่านยาก Postman คือโปรแกรมที่ทำหน้าที่เดียวกัน (ยิง request ไปหา API) แต่มีหน้าจอกรอกข้อมูลแทนการพิมพ์คำสั่ง เหมาะกับตอนต้องทดสอบ API บ่อย ๆ หรือ endpoint ที่ซับซ้อน
1.5.1 เปิดใช้งาน Postman บนเบราว์เซอร์
- เปิดเบราว์เซอร์ไปที่ postman.com แล้วกด Sign up for free (สมัครด้วยอีเมลหรือบัญชี Google ก็ได้ ไม่มีค่าใช้จ่าย)
- หลังสมัครเสร็จจะเข้าสู่ Postman Web ที่
web.postman.coโดยอัตโนมัติ — ใช้งานผ่านเบราว์เซอร์ล้วน ๆ ไม่ต้องติดตั้งโปรแกรมตัวเต็ม
⚠️ ต้องติดตั้ง "Postman Desktop Agent" ก่อนยิง API ที่ localhost ได้ เบราว์เซอร์มีกฎความปลอดภัยที่กันเว็บหนึ่ง (
web.postman.co) ไม่ให้ยิง request ตรงไปที่localhostของเครื่องเรา Postman จึงต้องอาศัยโปรแกรมเล็ก ๆ ชื่อ Desktop Agent รันอยู่เบื้องหลังเป็นตัวกลางแทน — เมื่อเข้าเว็บ Postman ครั้งแรกจะมีข้อความแจ้งให้ดาวน์โหลด กดลิงก์ที่ให้มา ติดตั้ง แล้วเปิดโปรแกรมทิ้งไว้ (ไม่ต้อง login ซ้ำ) จากนั้นกลับไปที่แท็บเบราว์เซอร์ มุมขวาบนจะขึ้นจุดสีเขียว "Connected via Desktop Agent" แปลว่าพร้อมใช้งานอย่าสับสน Desktop Agent ไม่ใช่ Postman เวอร์ชันเต็ม เป็นแค่ตัวกลางเล็ก ๆ ที่ทำงานเงียบ ๆ อยู่เบื้องหลัง หน้าจอที่ใช้งานจริงยังคงเป็น
web.postman.coบนเบราว์เซอร์เหมือนเดิม
1.5.2 รู้จักหน้าจอพื้นฐาน
| ส่วนของหน้าจอ | ใช้ทำอะไร |
|---|---|
| แถบซ้ายสุด (Sidebar) | รายการ Workspace และ Collection — ที่เก็บ request ที่เคยสร้างไว้ เรียกกลับมาใช้ซ้ำได้ |
| Dropdown ตัวอักษร GET ด้านซ้ายของช่อง URL | เลือกประเภทคำขอ (GET, POST, PUT, DELETE ฯลฯ) — ค่าเริ่มต้นเป็น GET เสมอ ต้องเปลี่ยนเองถ้าจะส่งข้อมูล |
| ช่อง URL ยาว ๆ ตรงกลาง | พิมพ์ปลายทางที่จะยิง เช่น http://localhost:3000/api/books |
| ปุ่ม Send สีส้มด้านขวา | กดเพื่อส่งคำขอจริง |
| แถบแท็บ Params / Authorization / Headers / Body ใต้ช่อง URL | ตั้งค่ารายละเอียดของคำขอ — ที่ใช้บ่อยที่สุดคือ Body สำหรับใส่ข้อมูล JSON ตอนส่ง POST/PUT |
| พื้นที่ด้านล่างหลังกด Send | Response — แสดงรหัสสถานะ (เช่น 200, 400), เวลาที่ใช้, ขนาดข้อมูล และเนื้อหาที่ API ตอบกลับ |
1.5.3 ลองยิง request เดียวกับที่เพิ่งทำด้วย curl
- กด + (แท็บใหม่) หรือปุ่ม New → HTTP Request
- เปลี่ยน dropdown จาก
GETเป็นPOST - ช่อง URL พิมพ์
http://localhost:3000/api/books - คลิกแท็บ Body → เลือก raw → มุมขวาของแท็บเปลี่ยนจาก
Textเป็นJSON(ขั้นนี้สำคัญ ถ้าลืมเปลี่ยน API จะไม่รู้ว่าข้อมูลที่ส่งมาเป็น JSON) - พิมพ์ในกล่อง Body
{
"title": "",
"author": "x",
"year": 2020,
"categoryId": 1
}
- กด Send
✅ ต้องเห็น ในช่อง Response: สถานะ 400 Bad Request และเนื้อหาข้อความ "กรุณากรอกชื่อหนังสือ" — ผลลัพธ์เดียวกับตอนใช้ curl.exe เป๊ะ เพราะยิงไปหา endpoint และ ValidationPipe ตัวเดียวกัน
💡 ข้อดีของ Postman เทียบกับพิมพ์คำสั่งเอง
- ไม่ต้อง escape เครื่องหมายคำพูดเหมือนใน PowerShell — พิมพ์ JSON ได้ตามปกติ
- กด Save เก็บ request ไว้เป็น Collection เรียกกลับมายิงซ้ำได้ ไม่ต้องพิมพ์ใหม่ทุกครั้ง
- อ่านผลลัพธ์ง่ายกว่า มีสี ปุ่มพับ/ขยาย JSON ให้อัตโนมัติ (Pretty view)
❌ ถ้าขึ้น "Could not send request" หรือ error เกี่ยวกับ Agent → Desktop Agent ยังไม่ได้เปิด หรือปิดไปแล้ว กลับไปเปิดโปรแกรม Desktop Agent อีกครั้ง (ดู 1.5.1) แล้วกด Send ซ้ำ
Part 2 — เก็บงานให้เรียบร้อย
🗺️ ตำแหน่งตอนนี้ในระบบ
- ✅ เตรียมเครื่องมือ (ทำไปแล้ว)
- 🟢 Angular (frontend) ← กำลังทำส่วนนี้
- ✅ NestJS (backend) (ทำไปแล้ว)
- ✅ PostgreSQL (ฐานข้อมูล) (ทำไปแล้ว)
ต่อไป: ทบทวนภาพรวมทั้งระบบก่อนจบวิชา
2.1 เพิ่มหน้า 404
แก้ app.routes.ts เพิ่มบรรทัดสุดท้าย
{ path: '**', redirectTo: '' },
💡
**= ตรงกับทุก URL ที่ไม่ตรงกับข้างบนเลย ต้องอยู่ล่างสุดเสมอ เพราะหากอยู่ด้านบน จะดักทุก route ไว้ทั้งหมด
2.2 ทำให้ใช้บนมือถือได้
ตรวจว่าใน book-list.html ใช้คลาสแบบนี้
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
💡
sm:และlg:คือ responsive ของ Tailwind
- ไม่มีคำนำหน้า = ใช้กับทุกขนาด (มือถือ)
sm:= จอกว้างขึ้นเล็กน้อย → 2 คอลัมน์lg:= จอใหญ่ → 3 คอลัมน์หลักการนี้เรียกว่า mobile first คือออกแบบให้มือถือก่อน แล้วค่อยเพิ่มความซับซ้อนเมื่อจอใหญ่ขึ้น
ทดสอบโดยกด F12 แล้วกดไอคอนมือถือ ลองย่อขยายดู

2.3 ตรวจสอบว่าโค้ดพร้อมใช้งานจริง
cd C:\webdev\booklab
npm run build --workspace api
npm run build --workspace web
✅ ทั้งสองคำสั่งต้องไม่มี error
💡
buildต่างจากdevอย่างไร
dev= โหมดพัฒนา เน้นความเร็วในการแก้ไข ไฟล์ใหญ่ มีข้อมูล debugbuild= โหมดใช้งานจริง บีบอัดโค้ดให้เล็กที่สุด ตัดของที่ไม่ได้ใช้ทิ้งโค้ดที่รันได้ในโหมด dev อาจ build ไม่ผ่านก็ได้ จึงต้องทดสอบก่อนเสมอ
Part 3 — ทบทวนภาพรวมและถาม-ตอบ
🗺️ ตำแหน่งตอนนี้ในระบบ
- ✅ เตรียมเครื่องมือ (ทำไปแล้ว)
- ✅ Angular (frontend) (ทำไปแล้ว)
- ✅ NestJS (backend) (ทำไปแล้ว)
- ✅ PostgreSQL (ฐานข้อมูล) (ทำไปแล้ว)
ต่อไป: จบหลักสูตร 6 Section
เส้นทางข้อมูลทั้งระบบ

ผู้ใช้พิมพ์
↓
Component (Angular)
↓
Service → HttpClient
↓
HTTP Request (CORS: 4200 → 3000)
↓
NestJS Controller
↓
NestJS Service → Prisma
↓
PostgreSQL
↓
วิ่งกลับทางเดิมมาแสดงบนหน้าจอ
ลองอธิบายเส้นทางนี้ด้วยคำพูดของตัวเอง ทีละขั้น โดยไม่ดูใบงาน — ถ้าติดขั้นไหน นั่นคือจุดที่ควรกลับไปทบทวน
คำถามชวนคิด
- ทำไม frontend ถึงต่อฐานข้อมูลตรง ๆ ไม่ได้
interfaceกับDTOต่างกันตรงไหน และทำไมต้องมีทั้งสองอย่าง- ถ้าลบ
ValidationPipeออก จะเกิดอะไรขึ้น - signal กับตัวแปรธรรมดาต่างกันอย่างไร
✅ Checklist สิ่งที่ควรทำได้แล้วตอนนี้
-
npm run devรันทั้งสองฝั่งได้บนเครื่องของตัวเอง - PostgreSQL รันอยู่ และ
npm exec -- prisma studioเปิดได้ - จำได้ว่า
npm exec -- prisma migrate resetทำอะไร - สร้าง endpoint ใหม่ใน NestJS ได้โดยไม่ต้องดูใบงาน
- สร้าง component ใหม่ใน Angular และเพิ่ม route ได้
- เขียน service ที่ยิง API แล้วจัดการ 3 สถานะได้
- เปิด F12 → Network เป็นและอ่านผลได้
ถ้ายังไม่มั่นใจข้อไหน กลับไปทบทวนใบงาน Section ที่เกี่ยวข้องได้เสมอ
📌 สรุปสิ่งที่ทำได้แล้วหลังจบ 12 ชั่วโมง
ผู้ใช้ ↔ Angular (frontend)
↕ HTTP
NestJS (backend)
↕ Prisma
PostgreSQL
- ออกแบบตารางและความสัมพันธ์ในฐานข้อมูลจริง
- สร้าง API ที่ ดู เพิ่ม แก้ ลบ ได้ครบ พร้อมตรวจสอบข้อมูล
- สร้างหน้าเว็บที่แยกเป็นชิ้นส่วน มีหลายหน้า มีฟอร์ม
- เชื่อมสองฝั่งเข้าด้วยกัน และจัดการกรณีที่ผิดพลาด
- เข้าใจว่าทำไมความลับต้องอยู่ฝั่งเซิร์ฟเวอร์
- ตรวจสอบได้ว่าโค้ด build ขึ้นใช้งานจริงผ่านไม่มี error
หัวข้อที่ควรเรียนต่อด้วยตัวเอง: ระบบล็อกอินและสิทธิ์ผู้ใช้, การอัปโหลดไฟล์, การแบ่งหน้า, การเขียนเทสต์, RxJS, Docker