Code Constructs Promoting Security
คำตอบและหมุดเชื่อมโยง: คำว่า "Code constructs promoting security" ตั้งขึ้นเพื่อท้าทายความเชื่อผิดๆ ที่ว่า "การเขียนโค้ดปลอดภัยต้องใช้ไลบรารีพิเศษ หรือเครื่องมือชั้นสูงที่ยุ่งยาก"
ความจริงแล้ว โครงสร้างภาษาธรรมดาที่เราใช้ทุกวัน เช่น คีย์เวิร์ด final (Immutability), การรับค่าผ่าน Constructor แทน Setter, และการวาง Precondition ดักจับค่าผิดพลาดที่หัวเมธอด (Design by Contract & Fail-Fast) คือ เกราะคุ้มกันความปลอดภัยชั้นยอด ที่ช่วยกำจัดปัญหา Data Integrity (ข้อมูลไม่ถูกบิดเบือน) และ Data Availability (ระบบไม่ค้างจาก Thread Contention) โดยไม่ต้องเขียนโค้ดตรวจจับการโจมตีเพิ่มเติมเลยแม้แต่บรรทัดเดียว!
Day 1: Security as a Concern & CIA-T / Day 2: The Anti-Hamlet (-1 เล่ม) / Day 3: DDD Core Tools (Entities, Value Objects, Aggregates, Bounded Contexts)
Day 4 จาก 14 วัน — เข้าสู่ใจกลาง Part 2: Fundamentals แปลงมโนทัศน์ DDD สู่โครงสร้างระดับโค้ด
ควบคุม Data Integrity & Availability ด้วย Immutability, Fail-Fast Contracts และ Validation Pipeline 5 ชั้น
เรื่องราวและมโนทัศน์เชิงลึก (Narrative Scenarios & Core Constructs)
📖 เรื่องราวจริงในระบบร้านค้าออนไลน์
ร้านค้าออนไลน์เปิดตัวแคมเปญลดราคาครั้งใหญ่ มีผู้ใช้แห่เข้ามารุมสั่งซื้อพร้อมกันหลายพันคน วันถัดมาฝ่ายการเงิน (Finance) แทบช็อก เมื่อพบว่าลูกค้าจำนวนมากที่มี Credit Score ต่ำมาก (ติดแบล็กลิสต์ ไม่ผ่านเกณฑ์) กลับสามารถกดเลือกตัวเลือก "ชำระเงินด้วยใบแจ้งหนี้ (Pay by Invoice)" แล้วให้ร้านส่งของไปก่อนได้ ส่งผลให้บริษัทเสี่ยงต่อหนี้สูญมหาศาล!
Customer และ CreditScore เป็นแบบ Mutable Object ที่มี Setter เปิดทิ้งไว้ ทำให้โค้ดส่วนอื่นแอบแก้ไขค่าได้ แถมโปรแกรมเมอร์ยังแก้ปัญหาการชนกันด้วยการใส่ synchronized ทุกเมธอด!
🧠 2 คลื่นวิกฤตความปลอดภัยจาก Mutable Object
setCreditScore(...) หรือสลับอ้างอิงข้ามลูกค้าได้ตามใจชอบ
synchronized บังคับให้พันๆ Threads ต้อง "ยืนต่อแถวเข้าคิวรออ่านทีละคน" เกิด Thread Contention รุนแรง เซิร์ฟเวอร์ค้าง และระบบล่มทันที
📜 กฎสัญญาของสมาคมพัฒนาสายพันธุ์แมว (Contract Rules)
คลาส CatNameList ทำหน้าที่เก็บคิวชื่อที่อนุมัติแล้วเพื่อเตรียมตั้งให้ลูกแมวเพิ่งเกิด โดยมีกฎเคร่งครัด:
- ชื่อแมวห้ามเป็น
nullเด็ดขาด - ชื่อแมวที่ดีต้องมีตัวอักษร
's'ประกอบอยู่ด้วยเสมอ (เช่น Simba, Sammy) - ห้ามป้อนชื่อแมวซ้ำลงในคิว
Fido หรือ null หลุดเข้าไป โปรแกรมจะไม่พังทันที แต่อีก 3 เดือนข้างหน้าเมื่อนำชื่อไปจดทะเบียน ระบบจะล่มหรือออกใบเพ็ดดีกรีผิดตัว กลายเป็นความเสียหายสะสมที่ตามสืบต้นตอไม่ได้
⚡ สวมสเกล 3 เสาหลัก Design by Contract (Bertrand Meyer)
หนังสือเสนอแนวคิดว่า "การบอกว่าให้ตรวจข้อมูลนำเข้า โดยไม่บอกลำดับ ก็เหมือนบอกว่าขับรถอย่าชน" เราต้องเรียงลำดับการตรวจสอบจาก "ต้นทุนทรัพยากร CPU/RAM ต่ำสุด ไปหาขั้นตอนที่แพงที่สุด (ต้องคุยกับ Database/Disk)" เพื่อให้ด่านหน้าที่ทำงานรวดเร็ว ช่วยสกัดข้อมูลขยะและแฮกเกอร์ออกไปก่อนถึงด่านหลัง:
เช็ก IP Address หรือ Access Key จากขอบเครือข่าย สกัดบอทและ DDoS นอกด่าน
ตรวจความยาว String / ขนาดไฟล์ เช่น ต้องยาว 10 ตัวอักษรพอดี ป้องกัน DoS ล้น RAM
สแกนดูชุดตัวอักษรและ Token สั้นๆ โดยยังไม่เริ่ม Parse (เช่น สกัด <!ENTITY ทันที)
ตรวจไวยากรณ์ โครงสร้างลึก (Regexp เฉพาะทาง, JSON/XML Parser, Checksum Digit)
ตรวจสอบความหมายกับฐานข้อมูล (เช่น มีสินค้านี้ในคลังไหม, ออเดอร์ถูกปิดไปแล้วหรือยัง)
แบบฝึกหัดปฏิบัติตามสถานการณ์จริง (Hands-on Refactoring)
// โค้ดเดิม: เปิด Setter และล็อกด้วย synchronized public class Customer { private String id; private CreditScore creditScore; // ช่องโหว่ 1: No-arg constructor สร้างวัตถุไม่สมบูรณ์ public Customer() {} // ช่องโหว่ 2: เปลี่ยนค่าได้ตลอดเวลา (Initialization Injection) public synchronized void setCreditScore(CreditScore score) { this.creditScore = score; } // ช่องโหว่ 3: ส่งคืน mutable reference (Escaping reference) public synchronized CreditScore getCreditScore() { return creditScore; } // ช่องโหว่ 4: Thread Contention จาก synchronized เมื่องานโหลดสูง public synchronized boolean isAcceptedForInvoicePayment() { return creditScore.compute() > 500; } }
synchronized บังคับให้เธรดต้องเข้าคิวรอจนเกิด Self-inflicted DoS ทันที!
import static org.apache.commons.lang3.Validate.*; // 1. Immutable Value Object พร้อม Fail-Fast Invariant public final class CreditScore { private static final int MIN_INVOICE_SCORE = 500; private final int score; public CreditScore(int computedScore) { isTrue(computedScore >= 0, "Credit score cannot be negative"); this.score = computedScore; } public boolean isAcceptedForInvoicePayment() { return score > MIN_INVOICE_SCORE; } } // 2. Immutable Entity ปลอดภัยข้าม Threads โดยไม่ต้องใช้ synchronized public final class Customer { private final CustomerId id; private final CreditScore creditScore; public Customer(CustomerId id, CreditScore creditScore) { this.id = notNull(id, "CustomerId required"); this.creditScore = notNull(creditScore, "CreditScore required"); } public CustomerId id() { return id; } public CreditScore creditScore() { return creditScore; } public boolean isAcceptedForInvoicePayment() { return creditScore.isAcceptedForInvoicePayment(); } }
ชุดควิซประเมินความรู้ประจำวัน
ตอบปุ๊บ รู้ผลเฉลยทันที พร้อมคำอธิบายและหลอดพลังงาน Energy Charge
ทดสอบความรู้ Day 4 สำเร็จแล้ว!
สรุปการเชื่อมโยงกลับสู่ Chapter 4 — Code constructs promoting security
เรื่องราวของปัญหาคะแนนเครดิตในร้านค้าออนไลน์, ระบบคิวชื่อแมว, และด่านตรวจค้น 5 ชั้นในวันนี้ ล้วนตอกย้ำให้เห็นอย่างเด่นชัดว่า "โครงสร้างโค้ดที่ถูกต้อง (Code constructs) คือเกราะคุ้มกันความปลอดภัยที่ทรงพลัง" การเลือกใช้ Immutability ช่วยขจัด Thread Contention และล็อก Integrity ของข้อมูล, การใช้ Fail-Fast Contracts ช่วยตัดข้อมูลขยะตั้งแต่ประตูหน้า, และการเรียงลำดับ Validation Pipeline อย่างชาญฉลาด ช่วยปกป้องระบบจาก DoS โดยที่เราไม่ต้องเขียนโค้ดเพื่อสู้กับแฮกเกอร์โดยตรงเลยครับ!