สัญญาของทางเข้า ที่มีหนึ่งแถวซึ่งระบบยังทำไม่ได้
ตัวเลขที่กระจายอยู่คนละบท ไม่ใช่สัญญา · มันกลายเป็นสัญญาเมื่อเขียนรวมกันในที่เดียว แล้วมีเทสต์ที่แดงได้จริงคอยเฝ้า
สัญญาทั้งคอร์ส ในตารางเดียว
หัวข้อที่มีชื่อว่า “สัญญาทั้งคอร์ส ในตารางเดียว”ผู้เรียกแต่ละแบบ เรียกอะไรได้ ได้รหัสอะไร มี body กี่คีย์ และเห็นกี่แถว
| ผู้เรียก | ปลายทาง | รหัส | คีย์ใน body | แถว |
|---|---|---|---|---|
| ยังไม่ยืนยันตัว | GET /open | 200 | 1 | — |
| ยังไม่ยืนยันตัว | GET /admin | 401 | 5 | — |
| รหัสผ่านผิด | GET /admin | 401 | 5 | — |
| ยืนยันตัวแล้ว สิทธิ์ไม่พอ | GET /admin | 403 | 5 | — |
ยืนยันตัวแล้ว สังกัด clinic-a | GET /visits | 200 | 2 | 2 |
แถวสุดท้ายของตารางนี้ตอบคำถามครึ่งหลังของชื่อคอร์ส · ฐานข้อมูลมีคนไข้สามแถว ผู้เรียกคนนี้เห็นสองแถว
แต่ละหลักประกัน ถูกบังคับด้วยอะไร
หัวข้อที่มีชื่อว่า “แต่ละหลักประกัน ถูกบังคับด้วยอะไร”สัญญาที่ไม่มีใครบังคับ คือคำอธิบายที่จะค่อยๆ กลายเป็นเท็จ
| หลักประกัน | ผู้บังคับ | บทที่ |
|---|---|---|
| ใครเรียกปลายทางไหนได้ | authorizeHttpRequests ใน chain | 2 |
| คนที่ไม่ผ่านได้รหัสอะไร | AuthenticationTrustResolver | 3 |
| chain ตัวไหนรับคำขอ | ลำดับของ @Order ที่ runtime ตรวจให้ | 4 |
| คำตอบที่ปฏิเสธมี body | AuthenticationEntryPoint และ AccessDeniedHandlerAccessDeniedHandlerตัวที่เขียนคำตอบให้ผู้เรียกที่ยืนยันตัวแล้วแต่ไม่มีสิทธิ์ · คู่กับตัวบนคือสองที่ที่ต้องเขียนเอง ถ้าอยากให้ body ของ security กลับเข้าสัญญาเดิม | 5 |
| กฎอ้างสิทธิ์ที่มีอยู่จริง | รายการใน Authentication | 6 |
| ผู้เรียกเห็นแถวของตัวเอง | เงื่อนไขใน query | 7 |
หลักประกันหกข้อถูกบังคับจากหกที่ ไม่มีที่เดียวที่เห็นครบทุกข้อ · access contractaccess contractตารางที่บอกว่าผู้เรียกแต่ละแบบเรียกอะไรได้ ได้รหัสอะไรกลับ และเห็นกี่แถว · เป็นสัญญาก็ต่อเมื่อมีเทสต์ที่แดงได้จริงเมื่อช่องใดช่องหนึ่งเปลี่ยน จึงต้องเขียน เป็นตาราง ไม่ใช่ฝากไว้กับความจำของคนที่เขียน config
หนึ่งแถวที่ระบบยังทำไม่ได้
หัวข้อที่มีชื่อว่า “หนึ่งแถวที่ระบบยังทำไม่ได้”คอร์สจบด้วยการบอกว่าอะไรยังไม่เสร็จ ไม่ใช่ด้วยการบอกว่าเสร็จแล้ว
บทที่ 7 วัดได้ว่าปลายทางที่กันด้วยกฎระดับ method คืน 500 ไม่ใช่ 403
· ถ้าเขียนลงตารางตามที่วัดได้ตรงๆ แถวนั้นจะเป็นแบบนี้
| ผู้เรียก | ปลายทาง | รหัสที่ควรได้ | รหัสที่ได้จริง |
|---|---|---|---|
| ยืนยันตัวแล้ว สิทธิ์ไม่พอ | GET /guarded | 403 | 500 |
ช่องขวาสุดคือหนี้ที่คอร์สนี้เปิดทิ้งไว้โดยตั้งใจ · ทางแก้มีสองทาง
- เพิ่ม handler ของ
AuthorizationDeniedExceptionลงใน advice ตัวเดิม ให้ตอบ403แทน handler ของException - ใช้ @HandleAuthorizationDenied@HandleAuthorizationDeniedการเปลี่ยนการปฏิเสธจากการโยน exception เป็นการคืนค่าแทน · เปลี่ยนคำตอบจากรหัสข้อผิดพลาด เป็นคำตอบที่สำเร็จแต่ไม่มีข้อมูลข้างใน เปลี่ยนการปฏิเสธจากการโยน เป็นการคืนค่าที่ว่างเปล่า
ถ้าสัญญาที่คุณเขียนไม่มีแถวไหนแดงเลย ให้ถามว่ามันถูกเขียนหลังจากดูผลลัพธ์แล้วหรือเปล่า
สัญญาที่ดีเขียนจากสิ่งที่ควรเป็น แล้วปล่อยให้การวัดชี้ว่าช่องไหนยังไม่ถึง
เทสต์ที่เฝ้าตารางนี้
หัวข้อที่มีชื่อว่า “เทสต์ที่เฝ้าตารางนี้”ผูกตัวหนังสือในบทเรียน เข้ากับค่าที่ probe วัดได้ ทีละช่อง
ทุกตัวเลขในหน้านี้ถูกเทียบกับ src/data/perf/clinic-security.ts ซึ่ง probe สร้างใหม่
จาก Spring Boot ตัวจริง · เปลี่ยนตัวเลขในตารางโดยไม่วัดใหม่ แล้วเทสต์แดงทันที
นั่นคือความต่างระหว่างตารางที่เป็นสัญญา กับตารางที่เป็นภาพประกอบ
สิ่งที่คอร์สนี้จงใจไม่แตะ
หัวข้อที่มีชื่อว่า “สิ่งที่คอร์สนี้จงใจไม่แตะ”ขอบเขตที่ประกาศไว้ตั้งแต่ต้น และไม่ได้ขยายระหว่างทาง
- OAuth2 กับ OIDC ทั้งระบบ · คอร์สนี้ใช้การยืนยันตัวแบบง่ายที่สุด เพื่อให้คำถามอยู่ที่กลไก ไม่ใช่ที่การตั้งค่า
- หน้า login · ทุกอย่างวัดจากฝั่งผู้เรียกที่เป็นตัว API
- CSRF กับ CORS · เป็นคนละคำถาม และจะทำให้แปดบทไม่พอ
- การเข้ารหัสรหัสผ่าน · เป็นเรื่องของคอร์ส security ทั่วไป ไม่ใช่ของทางเข้านี้
- ความเร็ว · ทั้งคอร์สไม่มีหน่วยเวลาสักตัว โดยตั้งใจ
จบคอร์ส
หัวข้อที่มีชื่อว่า “จบคอร์ส”คอร์สนี้เริ่มด้วยคำถามสองข้อ และตอบทั้งสองข้อด้วยตัวเลข
ใครเรียกได้ · ตอบด้วยรหัส 401 กับ 403 และกลไกที่เลือกระหว่างสองตัวนั้น
เห็นข้อมูลของใคร · ตอบด้วยจำนวนแถว ซึ่งเป็นหน่วยเดียวที่จับการรั่วชนิดนี้ได้ เพราะคำขอที่รั่วนั้นสำเร็จทุกครั้ง
- Spring Boot 4.1.1 · Spring Security 7.1.1 · Kotlin 2.4.10 · JDK 25 · PostgreSQL 18
- รันซ้ำเองได้ด้วย
npm run verify:clinic-security· ต้องสั่งscripts/clinic-security/up.shก่อน เพราะแถวสุดท้ายของตารางต้องใช้ฐานข้อมูลจริง - ทุกช่องในสองตารางถูกตรึงไว้ที่
src/data/perf/clinic-security.tsและtest/course-clinic-security.test.tsผูกตัวเลขในบทเข้ากับ file นั้น
เช็กความเข้าใจ — บทที่ 8
ข้อ 1 / 3ทำไมสัญญาของทางเข้าถึงต้องเขียนเป็นตาราง แทนที่จะอธิบายเป็นความ