Security & Performance
ทุกบทเรียนที่ผ่านมาล้วนยกย่องความยืดหยุ่นของ GraphQL: endpoint เดียว, graph ที่มี type กำกับ, และ client ที่ขอ field เฉพาะ ที่ต้องการได้พอดี ความยืดหยุ่นเดียวกันนี้เองคือเหตุผลที่ GraphQL ต้องมีคู่มือด้าน security และ performance เป็นของตัวเอง ฟีเจอร์ที่ทำให้ทีม front-end หลงรัก — “ขออะไรก็ได้ที่เข้าถึงได้” — ก็เป็นคำเชิญที่เปิดกว้างให้ใครก็ตามที่อยากขอ มากเกินไป เช่นกัน
หนึ่ง endpoint สองด้าน
หัวข้อที่มีชื่อว่า “หนึ่ง endpoint สองด้าน”REST API กระจาย API surface ออกไปตาม URL ตายตัวจำนวนมาก แต่ละ URL ทำงานเล็ก ๆ ที่คาดเดาได้ ส่วน GraphQL API ยุบทั้งหมดเหลือ endpoint เดียวที่รับ query อะไรก็ได้ที่ client เขียนขึ้นเอง พลังกับความเสี่ยงจึงเป็นสองด้านของเหรียญเดียวกัน:
- Power — client ประกอบรูปทรงของ response ที่ต้องการได้แม่นยำใน round trip เดียว โดยเดินผ่านความสัมพันธ์ที่ server ไม่เคยต้องคาดการณ์ล่วงหน้า
- Risk — client (หรือผู้โจมตี) สามารถประกอบ query ที่ server ก็ ไม่เคยคาดการณ์ไว้เช่นกัน: ซ้อนลึกมาก, ใช้ alias อย่างบ้าคลั่ง, หรือแตกกระจายออกไปเป็น database call นับพันครั้งจากคำขอเดียวที่ดูไร้พิษภัย
เพราะ server ไม่มีทางรู้ล่วงหน้าว่าจะเจอ query แบบไหน จึงต้องวิเคราะห์ cost, identity และ trust ราย request แบบ dynamic นั่นคือภารกิจทั้งหมดของโมดูลนี้
จุดกดดันทั้งสี่
หัวข้อที่มีชื่อว่า “จุดกดดันทั้งสี่”การทำให้ GraphQL API ปลอดภัยและจูนได้ สรุปเหลือคำถามสี่ข้อที่วนกลับมาเสมอ จำสี่ข้อนี้ไว้ แล้วที่เหลือของโมดูลก็เป็นแค่รายละเอียด:
- ใครเป็นคนถาม? — สร้าง identity ครั้งเดียวต่อ request นี่คือ authentication ที่ควรอยู่ใน context ของ request ไม่ใช่ใน schema
- เขาได้รับอนุญาตไหม? — ตัดสินทีละ field ทีละ type ว่า identity นี้เห็นข้อมูลนี้ได้หรือไม่ นี่คือ authorization ที่อยู่ใน resolver, directive หรือ middleware
- query นี้แพงแค่ไหน? — request เดียวจะถูกหรือจะหายนะก็ได้ Depth limiting และ complexity (cost) analysis ปฏิเสธ query ที่แพงเกินไปตั้งแต่ ก่อน รัน
- เราเคยเห็นสิ่งนี้มาก่อนไหม? — persisted queries, caching, และ rate limiting เปลี่ยนงานที่ทำซ้ำให้กลายเป็นงานที่ถูกและคาดเดาได้ พร้อมทั้งลดพื้นผิวการโจมตีลง
flowchart LR Q["Client query"] --> A["Authenticate: who is asking? (context)"] A --> Z["Authorize: are they allowed? (resolvers)"] Z --> C["Cost check: depth & complexity limits"] C --> X["Execute resolvers"] X --> D["Data sources"] X --> R["Response (cacheable, rate-limited)"] C -.->|"too deep / too costly"| Rej["Reject before execution"]
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”นี่คือโมดูล security และ performance ของคอร์ส เมื่อจบโมดูลนี้คุณจะสามารถล็อก GraphQL API ให้แน่นหนาได้โดยไม่ต้องเสียสละความสะดวกที่ทำให้คุณเลือกใช้ GraphQL ตั้งแต่แรก ห้าบทเรียนคือ:
- Security & Performance (คุณอยู่ที่นี่) — พื้นผิวของ threat และ cost ของ endpoint เดียวที่ยืดหยุ่น
- Authentication & Context — resolve current user ครั้งเดียวต่อ request จาก token และเหตุผลที่ context คือที่อยู่ที่เหมาะที่สุด
- Authorization — การตรวจ permission ระดับ field และ type และทางเลือกระหว่างการคืน
nullกับการ throw forbidden error - Depth & Complexity — การปฏิเสธ query ที่ลึก, ใช้ alias, หรือแพง ด้วย depth limit, cost analysis, และ timeout
- Persisted Queries & Caching — การทำ allowlist ของ operation, automatic persisted queries, response และ per-field caching, และ rate limiting
ตลอดทั้งโมดูล in-browser runner จะรัน logic ที่เกี่ยวกับ security จริง ๆ — resolver ที่อ่าน context ที่ authenticate แล้ว, field ที่ปฏิเสธผู้ใช้ที่ไม่ได้รับอนุญาต, และฟังก์ชันที่วัด depth ของ query ที่ parse แล้ว — เพื่อให้คุณได้เห็นกลไกทำงานจริงแทนที่จะต้องเชื่อโดยไม่มีหลักฐาน