🛑 1. The Problem First: "หน้าลับที่ใครก็แอบดูได้" (The Client-Side Mirage)
ลองนึกถึงแอปที่คุณพยายามป้องกันหน้า Dashboard โดยใช้เพียง JavaScript ในฝั่ง Client:
// ❌ Naive Approach: เช็คสิทธิ์ในระดับ Component
if (!user) {
router.push('/login');
return null;
}
// 🌋 พัง! แม้หน้าจะเปลี่ยนไป แต่ Browser ยังต้องโหลดโค้ดของหน้านั้นมาแล้ว
# และแฮกเกอร์ที่เก่งหน่อยสามารถกดหยุด (Stop) การทำงานของ JS
# เพื่อแอบดูข้อมูลที่แวบขึ้นมาก่อนหน้า หรือแอบดู API Response ที่หลุดออกมาได้
ปัญหา: การเช็คสิทธิ์หลังจากที่หน้าเว็บโหลดมาแล้ว (Client-side Check) คือการ "วัวหายล้อมคอก" ข้อมูลบางส่วนอาจหลุดออกไปถึงเครื่องผู้ใช้แล้วก่อนที่คุณจะทำการ Redirect นี่คือช่องโหว่พื้นฐานที่ระบบระดับองค์กรรับไม่ได้ครับ
💡 2. Real-Life Analogy: ยามเฝ้าประตูหมู่บ้าน vs กล้องวงจรปิดในบ้าน
- Middleware: เหมือน "รปภ. ที่ด่านหน้าหมู่บ้าน". ถ้าคุณไม่มีบัตรสมาชิก เขาจะไม่ปล่อยให้คุณขับรถเข้ามาในซอยเลยด้วยซ้ำ คุณจะไม่มีทางได้เห็นหน้าบ้าน (Page Content) ของใครทั้งนั้น
- Server-Side Session Check: เหมือน "พนักงานธนาคารที่ขอดูบัตรประชาชน". แม้คุณจะเดินเข้ามาในธนาคารได้แล้ว แต่เวลาจะถอนเงิน (Server Action) เขาจะเช็คอีกครั้งเพื่อให้มั่นใจว่าคุณคือเจ้าของบัญชีตัวจริง
- Matchers: เหมือน "รายชื่อบ้านที่ต้องตรวจบัตร". รปภ. จะเข้มงวดเฉพาะซอยบ้านเศรษฐี (Dashboard) แต่ซอยที่มีร้านสะดวกซื้อ (Public Page) เขาจะปล่อยให้ผ่านไปได้เลยเพื่อไม่ให้รถติด
🚀 3. Execution Journey: มหากาพย์การสร้างด่านตรวจที่ไร้ช่องโหว่
Senior จะใช้ Edge Middleware ในการคัดกรอง Request ตั้งแต่ระดับ Network ชั้นนอกสุด
🛠 Step-by-step:
- The Gatekeeper: สร้างไฟล์
middleware.tsเพื่อเช็ค Cookie ทันทีที่ Request วิ่งเข้ามา - The Smart Redirect: ส่งผู้ใช้ที่ไม่มีสิทธิ์ไปยังหน้า Login พร้อมแนบ
callbackUrlเพื่อให้เขากลับมาที่เดิมได้หลัง Login - The Secure Boundary: ใช้
matcherเพื่อจำกัดวงการทำงานของ Middleware ไม่ให้รันในหน้า Static/Public (ประหยัดหน่วยประมวลผล) - The Double Check: ตรวจเช็ค Session ซ้ำอีกครั้งใน
Server Actionsเพราะมันคือทางเข้าหลักของการแก้ไขข้อมูล
// ✅ Best Practice: Middleware หุ้มเกราะเหล็ก
export function middleware(req: NextRequest) {
const token = req.cookies.get("auth-token");
// 🛠 ดักจับตั้งแต่ยังไม่ถึง Page (Edge Runtime)
if (!token && req.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", req.url));
}
return NextResponse.next();
}
// 🛠 ล็อกเป้าหมายเฉพาะหน้าที่ต้องการความปลอดภัย
export const config = {
matcher: ["/dashboard/:path*", "/settings/:path*"],
};
🪤 4. The Junior Trap: โรค "Middleware Overload"
จูเนียร์มักจะตื่นเต้นกับ Middleware และยัดทุุกอย่างลงไปในนั้น:
// ❌ Junior Trap: ดึงข้อมูลจากฐานข้อมูลใน Middleware
const user = await db.user.findFirst(...); // 🌋 พัง!
# Middleware รันบน 'Edge Runtime' ซึ่งมีทรัพยากรจำกัดมาก และต้องเน้นความเร็วสูง
# การต่อ Database ตรงๆ ในนี้จะทำให้หน้าเว็บคุณอืดทุุกครั้งที่โหลด (Latency เพิ่มขึ้นมหาศาล)
ระวัง: Middleware ควรทำงานแค่เรื่อง Routing และ Simple Check เท่านั้น ✅ การแก้ไข: จงทำแค่การเช็ค 'ความมีอยู่' ของ Token และปล่อยให้เรื่อง Logic หนักๆ เป็นหน้าที่ของ Page หรือ Server Action ครับ
⚖️ 5. The Why Matrix: Client Check vs Middleware vs API Guard
| หัวข้อ | Client Check (Naive) | Middleware (Senior) | Server Action Guard |
|---|---|---|---|
| UX (ความลื่นไหล) | 🐢 ต่ำ (หน้าขาวแวบหนึ่ง) | 🚀 ดีที่สุด (Redirect ทันที) | - |
| Security (ความมั่นคง) | ต่ำ (ข้อมูลหลุดง่าย) | ⚡⚡ สูงมาก | 🚀 สูงสุด (ด่านสุดท้าย) |
| ความเร็ว | เร็ว (ไม่ต้องผ่าน Server) | ⚡⚡ รวดเร็ว (Edge Runtime) | ปานกลาง (ต้องรัน Logic) |
| หน้าที่หลัก | แสดงผล UI | ควบคุมการเข้าถึง | รักษาความปลอดภัยข้อมูล |
🎓 6. Senior Mindset Summary
การเป็น Senior คือการมองว่า "เราไม่ได้เช็ค Auth เพื่อกั้นคนนอกเพียงอย่างเดียว แต่เพื่อส่งมอบหน้าเว็บที่ถูกต้องให้กับคนที่มีสิทธิ์อย่างรวดเร็วที่สุด". Middleware คือตัวตัดสินว่าบ้านของคุณจะดูเป็นมืออาชีพหรือดูเหมือนบ้านที่สร้างไม่เสร็จในสายตาผู้ใช้งานครับ!