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

💡 การโจมตีแบบนี้เรียกว่า XSS — คือการแอบฝังโค้ดลงในช่องกรอกข้อมูล หวังให้เว็บเอาไปรันจริง ถ้าสำเร็จ ผู้โจมตีจะขโมยข้อมูลผู้ใช้คนอื่นได้
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 เป็นช่องโหว่ที่ทำให้ระบบใหญ่ ๆ ล่มมาแล้วนับไม่ถ้วน
Prisma ป้องกันให้โดยอัตโนมัติ เพราะเราไม่ได้ต่อข้อความเอง แต่ส่งค่าแยกไปให้ฐานข้อมูลจัดการ ฐานข้อมูลจึงมองค่านั้นเป็น "ข้อมูล" เสมอ ไม่ใช่ "คำสั่ง"
นี่คือเหตุผลสำคัญข้อหนึ่งที่โลกจริงใช้ ORM
1.3 ตรวจว่าความลับไม่หลุด
เปิดโฟลเดอร์ apps/api ดูให้แน่ใจว่าไฟล์ .env อยู่ตรงนั้นที่เดียว
❌ ถ้าเผลอคัดลอกไฟล์นี้ไปไว้ที่อื่น (เช่น ส่งให้เพื่อนช่วยดูโค้ด หรือแนบไปกับข้อความ) ให้ลบทิ้งจากที่นั้นทันที
⚠️ ทำไมเรื่องนี้สำคัญ ถ้ามีใครเผลอส่งไฟล์นี้ให้คนอื่น เท่ากับแนบรหัสผ่านฐานข้อมูลของตัวเองไปให้คนอื่นเห็นด้วย
จากนั้นเปิด localhost:4200 กด F12 → แท็บ Sources แล้วเปิดดูไฟล์โค้ดของเรา
💡 สังเกตว่าโค้ด Angular ทั้งหมดอ่านได้หมด — ทุกคนที่เข้าเว็บเราเห็นสิ่งนี้ได้
นี่คือคำตอบของคำถามตั้งแต่คาบแรก ว่าทำไมหน้าบ้านต่อฐานข้อมูลตรง ๆ ไม่ได้ ถ้าเอา 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 เท่านั้น
ช่วงที่ 2 — เก็บงานให้เรียบร้อย (25 นาที)
🗺️ ตำแหน่งตอนนี้ในระบบ
- ✅ เตรียมเครื่องมือ (ทำไปแล้ว)
- 🟢 Angular (หน้าบ้าน) ← กำลังทำช่วงนี้
- 🟢 NestJS (หลังบ้าน) ← กำลังทำช่วงนี้
- ✅ PostgreSQL (ฐานข้อมูล) (ทำไปแล้ว)
ต่อไป: ทบทวนภาพรวมทั้งระบบก่อนจบวิชา
2.1 เพิ่มหน้า 404
แก้ app.routes.ts เพิ่มบรรทัดสุดท้าย
{ path: '**', redirectTo: '' },
💡
**= ตรงกับทุก URL ที่ไม่ตรงกับข้างบนเลย ต้องอยู่ล่างสุดเสมอ เพราะถ้าอยู่บน มันจะกินทุกเส้นทาง
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 ไม่ผ่านก็ได้ จึงต้องทดสอบก่อนเสมอ
ช่วงที่ 3 — ทบทวนภาพรวมและถาม-ตอบ (65 นาที)
🗺️ ตำแหน่งตอนนี้ในระบบ
- ✅ เตรียมเครื่องมือ (ทำไปแล้ว)
- 🟢 Angular (หน้าบ้าน) ← กำลังทำช่วงนี้
- 🟢 NestJS (หลังบ้าน) ← กำลังทำช่วงนี้
- 🟢 PostgreSQL (ฐานข้อมูล) ← กำลังทำช่วงนี้
ต่อไป: จบหลักสูตร 6 คาบ
ไม่มีโค้ดใหม่ให้เขียนแล้ว ใช้ช่วงนี้ทบทวนเส้นทางข้อมูลทั้งระบบและเปิดให้ถามคำถามที่ค้างใจตลอด 6 คาบ
เส้นทางข้อมูลทั้งระบบ

ผู้ใช้พิมพ์
↓
Component (Angular)
↓
Service → HttpClient
↓
HTTP Request (CORS: 4200 → 3000)
↓
NestJS Controller
↓
NestJS Service → Prisma
↓
PostgreSQL
↓
วิ่งกลับทางเดิมมาแสดงบนหน้าจอ
ลองอธิบายเส้นทางนี้ด้วยคำพูดของตัวเอง ทีละขั้น โดยไม่ดูใบงาน — ถ้าติดขั้นไหน นั่นคือจุดที่ควรกลับไปทบทวน
คำถามชวนคิด
- ทำไมหน้าบ้านถึงต่อฐานข้อมูลตรง ๆ ไม่ได้
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 เป็นและอ่านผลได้
ถ้ายังไม่มั่นใจข้อไหน กลับไปทบทวนใบงานคาบที่เกี่ยวข้องได้เสมอ
📌 สรุปสิ่งที่ทำได้แล้วหลังจบ 12 ชั่วโมง
ผู้ใช้ ↔ Angular (หน้าบ้าน)
↕ HTTP
NestJS (หลังบ้าน)
↕ Prisma
PostgreSQL
- ออกแบบตารางและความสัมพันธ์ในฐานข้อมูลจริง
- สร้าง API ที่ ดู เพิ่ม แก้ ลบ ได้ครบ พร้อมตรวจสอบข้อมูล
- สร้างหน้าเว็บที่แยกเป็นชิ้นส่วน มีหลายหน้า มีฟอร์ม
- เชื่อมสองฝั่งเข้าด้วยกัน และจัดการกรณีที่ผิดพลาด
- เข้าใจว่าทำไมความลับต้องอยู่ฝั่งเซิร์ฟเวอร์
- ตรวจสอบได้ว่าโค้ด build ขึ้นใช้งานจริงผ่านไม่มี error
หัวข้อที่ควรเรียนต่อด้วยตัวเอง: ระบบล็อกอินและสิทธิ์ผู้ใช้, การอัปโหลดไฟล์, การแบ่งหน้า, การเขียนเทสต์, RxJS, Docker