Rate Limiting & Validation
มีสองแนวป้องกันที่ทำให้ความปลอดภัยของ API สมบูรณ์ขึ้น: การจำกัดความถี่ที่ผู้เรียกใช้สามารถยิงเข้ามาหาคุณได้ และการไม่เชื่อสิ่งที่พวกเขาส่งมาเลย
Rate limiting
หัวข้อที่มีชื่อว่า “Rate limiting”Rate limiting จำกัดจำนวน request ต่อ client ในแต่ละช่วงเวลา (window) เพื่อกันทั้งการใช้งานในทางที่ผิด client ที่ทำงานเพี้ยน และลูปที่หลุดมาโดยไม่ตั้งใจ เมื่อผู้เรียกเกินโควตา ให้ตอบ 429 Too Many Requests พร้อม header Retry-After บอกว่าให้กลับมาลองใหม่เมื่อไหร่ และควรประกาศ budget ที่เหลือไว้ด้วย header RateLimit-Limit, RateLimit-Remaining และ RateLimit-Reset
algorithm ที่พบบ่อยคือ token bucket: แต่ละ client มีถังหนึ่งใบที่เติม token กลับเข้าไปด้วยอัตราคงที่ แต่ละ request ใช้ token ไปหนึ่งตัว ถังที่ว่างเปล่าหมายถึง 429
validate ทุกอย่าง
หัวข้อที่มีชื่อว่า “validate ทุกอย่าง”ทุกค่าที่มาจาก client เชื่อถือไม่ได้จนกว่าจะผ่านการ validate ความเสี่ยงหลัก ๆ ได้แก่:
- Injection — อย่าสร้าง SQL/command ด้วยการต่อ string เด็ดขาด ให้ใช้ parameterized query
- Mass assignment — อย่าเอา request body ไป spread ทับลงบน model แบบไม่ดูตาม้าตาเรือ ให้รับเฉพาะ field ที่อยู่ใน allowlist เท่านั้น มิฉะนั้น user อาจตั้งค่า
isAdmin: trueได้ - Oversized payloads — จำกัดขนาด request body และความยาวของ array เพื่อหลีกเลี่ยงการทำให้ resource หมดเกลี้ยง
- Type and range — validate ชนิดข้อมูล, ความยาว และช่วงค่าด้วย schema และปฏิเสธด้วย
422(ดู Validation Errors)
| ข้อดี (Rate Limiting) | ข้อแลกเปลี่ยน |
|---|---|
| ป้องกัน abuse และ DDoS | legitimate spike traffic อาจ fail |
| ป้องกัน credential stuffing และ brute force | ต้องออกแบบ limit ที่เหมาะสม — ไม่เข้มเกินหรือหย่อนเกิน |
| ลด cost ของ downstream service เช่น LLM API | rate limit shared ใน distributed system ต้องใช้ Redis |
| บอก client ผ่าน header ว่าเหลือ quota เท่าไร | user experience แย่ถ้า error ไม่อธิบาย |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”Rate Limit โดยไม่บอก Client อาการ:
- 429 Too Many Requests โดยไม่มี header บอกว่าเหลือ quota เท่าไรและ reset เมื่อไร
- client ไม่รู้ว่าต้องรอนานแค่ไหน — retry loop ทำให้แย่ลง
- ส่ง
Retry-After,X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Resetเสมอ
Input Validation ที่ไม่ Sanitize อาการ:
- รับ
name: "<script>alert(1)</script>"แล้วเก็บและแสดงโดยไม่ sanitize - XSS เมื่อ API response ไปแสดงใน web app
- validate type/format และ sanitize string input ก่อน store
💡 ตัวอย่างจากของจริง
GitHub API:
- rate limit: 5000 requests/hour สำหรับ authenticated request
- header:
X-RateLimit-Limit: 5000,X-RateLimit-Remaining: 4999,X-RateLimit-Reset: 1609459200Stripe API:
- rate limit ตาม endpoint:
/chargesมี limit ต่างจาก/events- 429 พร้อม
Retry-Afterheader — client รู้ว่าต้องรอกี่วินาที