🛠️
14-Day Mastery Roadmap

SECURE BY DESIGN DAY 04

เริ่มทำควิซ ⚡
Part 2: Fundamentals | Chapter 4

Code Constructs Promoting Security

Language-Level Armor 🛡️
📌 TITLE ANCHOR QUESTION ทำไมบทนี้ถึงชื่อนี้? และโครงสร้างโค้ดธรรมดาเกี่ยวข้องกับ Security อย่างไร?

คำตอบและหมุดเชื่อมโยง: คำว่า "Code constructs promoting security" ตั้งขึ้นเพื่อท้าทายความเชื่อผิดๆ ที่ว่า "การเขียนโค้ดปลอดภัยต้องใช้ไลบรารีพิเศษ หรือเครื่องมือชั้นสูงที่ยุ่งยาก"

ความจริงแล้ว โครงสร้างภาษาธรรมดาที่เราใช้ทุกวัน เช่น คีย์เวิร์ด final (Immutability), การรับค่าผ่าน Constructor แทน Setter, และการวาง Precondition ดักจับค่าผิดพลาดที่หัวเมธอด (Design by Contract & Fail-Fast) คือ เกราะคุ้มกันความปลอดภัยชั้นยอด ที่ช่วยกำจัดปัญหา Data Integrity (ข้อมูลไม่ถูกบิดเบือน) และ Data Availability (ระบบไม่ค้างจาก Thread Contention) โดยไม่ต้องเขียนโค้ดตรวจจับการโจมตีเพิ่มเติมเลยแม้แต่บรรทัดเดียว!

วันก่อนหน้า (Recap Days 1–3)

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)

ตำแหน่งปัจจุบัน (Where We Are)

Day 4 จาก 14 วัน — เข้าสู่ใจกลาง Part 2: Fundamentals แปลงมโนทัศน์ DDD สู่โครงสร้างระดับโค้ด

เป้าหมายประจำวัน (Core Mission)

ควบคุม Data Integrity & Availability ด้วย Immutability, Fail-Fast Contracts และ Validation Pipeline 5 ชั้น

02

เรื่องราวและมโนทัศน์เชิงลึก (Narrative Scenarios & Core Constructs)

🛒 SCENARIO 2.1 • โศกนาฏกรรมคะแนนเครดิตและการล่มของร้านค้าออนไลน์ (Webshop Credit Score Integrity Issue) Integrity & Availability

📖 เรื่องราวจริงในระบบร้านค้าออนไลน์

ร้านค้าออนไลน์เปิดตัวแคมเปญลดราคาครั้งใหญ่ มีผู้ใช้แห่เข้ามารุมสั่งซื้อพร้อมกันหลายพันคน วันถัดมาฝ่ายการเงิน (Finance) แทบช็อก เมื่อพบว่าลูกค้าจำนวนมากที่มี Credit Score ต่ำมาก (ติดแบล็กลิสต์ ไม่ผ่านเกณฑ์) กลับสามารถกดเลือกตัวเลือก "ชำระเงินด้วยใบแจ้งหนี้ (Pay by Invoice)" แล้วให้ร้านส่งของไปก่อนได้ ส่งผลให้บริษัทเสี่ยงต่อหนี้สูญมหาศาล!

💥 วิเคราะห์สาเหตุ (Root Cause): โปรแกรมเมอร์ออกแบบคลาส Customer และ CreditScore เป็นแบบ Mutable Object ที่มี Setter เปิดทิ้งไว้ ทำให้โค้ดส่วนอื่นแอบแก้ไขค่าได้ แถมโปรแกรมเมอร์ยังแก้ปัญหาการชนกันด้วยการใส่ synchronized ทุกเมธอด!

🧠 2 คลื่นวิกฤตความปลอดภัยจาก Mutable Object

1. หายนะ Data Integrity: มี Unrestricted Setter เปิดให้โค้ดจากภายนอกแอบเรียก setCreditScore(...) หรือสลับอ้างอิงข้ามลูกค้าได้ตามใจชอบ
2. หายนะ Data Availability (Self-inflicted DoS): การใช้ synchronized บังคับให้พันๆ Threads ต้อง "ยืนต่อแถวเข้าคิวรออ่านทีละคน" เกิด Thread Contention รุนแรง เซิร์ฟเวอร์ค้าง และระบบล่มทันที
🛡️ ทางรอดด้วย Immutability: เมื่อเป็น Immutable วัตถุจะอ่านพร้อมกันจากพัน Thread ได้อย่างเสรี "No locking, no blocking" ไม่ต้องใช้ synchronized อีกต่อไป!
🐱 SCENARIO 2.2 • ระบบจัดการรายชื่อลูกแมว และหลักการ DESIGN BY CONTRACT & FAIL-FAST Contract Enforcement

📜 กฎสัญญาของสมาคมพัฒนาสายพันธุ์แมว (Contract Rules)

คลาส CatNameList ทำหน้าที่เก็บคิวชื่อที่อนุมัติแล้วเพื่อเตรียมตั้งให้ลูกแมวเพิ่งเกิด โดยมีกฎเคร่งครัด:

  • ชื่อแมวห้ามเป็น null เด็ดขาด
  • ชื่อแมวที่ดีต้องมีตัวอักษร 's' ประกอบอยู่ด้วยเสมอ (เช่น Simba, Sammy)
  • ห้ามป้อนชื่อแมวซ้ำลงในคิว
❌ หากไม่ Fail-Fast: ถ้าปล่อยให้ชื่อผิด เช่น Fido หรือ null หลุดเข้าไป โปรแกรมจะไม่พังทันที แต่อีก 3 เดือนข้างหน้าเมื่อนำชื่อไปจดทะเบียน ระบบจะล่มหรือออกใบเพ็ดดีกรีผิดตัว กลายเป็นความเสียหายสะสมที่ตามสืบต้นตอไม่ได้

⚡ สวมสเกล 3 เสาหลัก Design by Contract (Bertrand Meyer)

1. Preconditions (เงื่อนไขก่อนรัน): สิ่งที่ผู้เรียก (Caller) ต้องปฏิบัติตามให้ถูกต้องก่อนเรียกเมธอด ตรวจสอบที่บรรทัดแรกสุด หากผิดต้อง Fail-Fast ทันที
2. Postconditions (เงื่อนไขหลังรัน): สิ่งที่เมธอดรับประกันว่าจะเป็นจริงหลังทำงานเสร็จสมบูรณ์
3. Invariants (กฎคงสภาพ): เงื่อนไขทางธุรกิจที่ต้องเป็นจริงเสมอสำหรับอ็อบเจกต์นั้นๆ ตั้งแต่วินาทีที่สร้างเสร็จตลอดอายุขัย
🛡️ SCENARIO 2.3 • ด่านตรวจค้น 5 ชั้นของ INPUT VALIDATION PIPELINE (COST-ORDERED FILTERING) Defense-in-Depth

หนังสือเสนอแนวคิดว่า "การบอกว่าให้ตรวจข้อมูลนำเข้า โดยไม่บอกลำดับ ก็เหมือนบอกว่าขับรถอย่าชน" เราต้องเรียงลำดับการตรวจสอบจาก "ต้นทุนทรัพยากร CPU/RAM ต่ำสุด ไปหาขั้นตอนที่แพงที่สุด (ต้องคุยกับ Database/Disk)" เพื่อให้ด่านหน้าที่ทำงานรวดเร็ว ช่วยสกัดข้อมูลขยะและแฮกเกอร์ออกไปก่อนถึงด่านหลัง:

1
Origin Check

เช็ก IP Address หรือ Access Key จากขอบเครือข่าย สกัดบอทและ DDoS นอกด่าน

ต้นทุน: ต่ำที่สุด
2
Size Check

ตรวจความยาว String / ขนาดไฟล์ เช่น ต้องยาว 10 ตัวอักษรพอดี ป้องกัน DoS ล้น RAM

ต้นทุน: ต่ำมาก O(1)
3
Lexical Check

สแกนดูชุดตัวอักษรและ Token สั้นๆ โดยยังไม่เริ่ม Parse (เช่น สกัด <!ENTITY ทันที)

ต้นทุน: ต่ำ O(N)
4
Syntax Check

ตรวจไวยากรณ์ โครงสร้างลึก (Regexp เฉพาะทาง, JSON/XML Parser, Checksum Digit)

ต้นทุน: ปานกลาง (CPU)
5
Semantic Check

ตรวจสอบความหมายกับฐานข้อมูล (เช่น มีสินค้านี้ในคลังไหม, ออเดอร์ถูกปิดไปแล้วหรือยัง)

ต้นทุน: สูงสุด (I/O & DB)
03

แบบฝึกหัดปฏิบัติตามสถานการณ์จริง (Hands-on Refactoring)

Before: Mutable & Synchronized Contention เสี่ยง Integrity & Thread Contention
// โค้ดเดิม: เปิด 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 ทันที!
After: Immutable & Fail-Fast Contracts No locking, no blocking 100%
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();
    }
}
🛡️ จุดเปลี่ยนสำคัญ: โค้ดกลายเป็น Immutable 100% ปราศจาก Setter, เธรดนับพันอ่านข้อมูลพร้อมกันได้โดยไม่ต้องมี Lock เลย (No locking, no blocking) และรับประกันว่าคะแนนเครดิตจะไม่ถูกแอบแก้ไขข้ามสายแน่นอน!
04

ชุดควิซประเมินความรู้ประจำวัน

ตอบปุ๊บ รู้ผลเฉลยทันที พร้อมคำอธิบายและหลอดพลังงาน Energy Charge

Energy Charge
0 / 10
📌 CLOSING TITLE CONNECTION WRAP-UP สรุปหมุดเชื่อมโยงกลับหาหัวข้อบท

สรุปการเชื่อมโยงกลับสู่ Chapter 4 — Code constructs promoting security

เรื่องราวของปัญหาคะแนนเครดิตในร้านค้าออนไลน์, ระบบคิวชื่อแมว, และด่านตรวจค้น 5 ชั้นในวันนี้ ล้วนตอกย้ำให้เห็นอย่างเด่นชัดว่า "โครงสร้างโค้ดที่ถูกต้อง (Code constructs) คือเกราะคุ้มกันความปลอดภัยที่ทรงพลัง" การเลือกใช้ Immutability ช่วยขจัด Thread Contention และล็อก Integrity ของข้อมูล, การใช้ Fail-Fast Contracts ช่วยตัดข้อมูลขยะตั้งแต่ประตูหน้า, และการเรียงลำดับ Validation Pipeline อย่างชาญฉลาด ช่วยปกป้องระบบจาก DoS โดยที่เราไม่ต้องเขียนโค้ดเพื่อสู้กับแฮกเกอร์โดยตรงเลยครับ!

พร้อมก้าวสู่เครื่องมือสำคัญในวันถัดไปแล้วหรือยัง? Next: Day 5 — Chapter 5: Domain primitives (อิฐบล็อกสยบช่องโหว่ความปลอดภัย) ➔