Frontend Academy · บทเรียน

Content Security Policy: nonce และแฮช

เขียน CSP ที่เข้มงวดด้วย nonce สำหรับสคริปต์อินไลน์ ใช้แฮชกับโค้ดที่รู้จัก และใช้ report-uri เพื่อตรวจสอบการละเมิดในระบบจริง

บทเรียน 3 จาก 414 ขั้นตอน

Content Security Policy: nonce และแฮช เป็นบทเรียน Frontend Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Frontend Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

สรุป CSP

CSP คือส่วนหัว HTTP ที่กำหนดรายการสิ่งที่เบราว์เซอร์อนุญาตให้โหลดได้ ทั้งสคริปต์ สไตล์ รูปภาพ แบบอักษร เฟรม และการเชื่อมต่อ การป้องกันหลายชั้นนี้ช่วยให้ CSP หยุดเพย์โหลดได้ในหลายกรณี แม้ XSS จะผ่านตัวกรองของคุณมาได้

โครงสร้างส่วนหัว CSP

แต่ละคำสั่งจะแสดงรายการแหล่งที่มาที่อนุญาต 'self' หมายถึงต้นทางเดียวกัน และยังอนุญาตให้ระบุ URL เฉพาะได้ด้วย

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  font-src 'self' https://fonts.gstatic.com;
  frame-ancestors 'none';
  base-uri 'self';

คำสั่งที่ใช้บ่อย

default-src: ค่าใช้แทนสำหรับทุกอย่าง script-src: JavaScript style-src: CSS img-src: รูปภาพ connect-src: fetch/XHR/WebSocket font-src: แบบอักษร frame-ancestors: ผู้ที่สามารถฝังหน้าเว็บของคุณในเฟรมได้ (การป้องกันการหลอกให้คลิก)

'unsafe-inline' — ช่องโหว่ที่พบบ่อย

หลายไซต์เพิ่ม 'unsafe-inline' เพื่ออนุญาตแท็ก <script> และแอตทริบิวต์ onclick แบบอินไลน์ วิธีนี้ทำลายจุดประสงค์หลักของ CSP เพราะเพย์โหลด XSS สามารถทำงานแบบอินไลน์ได้ ให้แทนที่ด้วยค่า nonce หรือค่า hash

ค่า nonce — รายการอนุญาตแบบใช้ครั้งเดียว

สร้างค่า nonce แบบสุ่มสำหรับแต่ละคำขอ ใส่ค่า nonce ให้กับสคริปต์อินไลน์ที่ถูกต้อง เบราว์เซอร์จะอนุญาตเฉพาะสคริปต์ที่มีค่า nonce ตรงกัน

// Server (Express middleware):
import crypto from 'crypto';

app.use((req, res, next) => {
  res.locals.nonce = crypto.randomBytes(16).toString('base64');
  res.setHeader('Content-Security-Policy',
    `script-src 'nonce-${res.locals.nonce}' 'strict-dynamic'`
  );
  next();
});

// Template:
<script nonce="<%= nonce %>">window.config = {...};</script>

'strict-dynamic'

ใช้ค่า nonce ร่วมกับ 'strict-dynamic' สคริปต์ที่เชื่อถือได้ (สคริปต์ที่มีค่า nonce) สามารถโหลดสคริปต์เพิ่มเติมได้ จึงไม่จำเป็นต้องระบุ URL ของแหล่งสคริปต์ทุกแห่ง นี่คือแนวทางปฏิบัติที่ดีที่สุดในปัจจุบันสำหรับ CSP

ค่า hash — รายการอนุญาตแบบคงที่

ใช้เทคนิคเดียวกันกับสคริปต์อินไลน์ที่ทราบและไม่เปลี่ยนแปลง (เช่น กระบวนการสร้างของคุณสร้างส่วนโค้ดเริ่มต้นเดิมทุกครั้ง) คำนวณค่า SHA-256 ของสคริปต์แล้วเพิ่มเป็นแหล่งที่มาประเภท hash จึงไม่ต้องสร้างค่า nonce สำหรับแต่ละคำขอ

// Hash of: console.log('hi');
Content-Security-Policy: script-src 'sha256-XwCNuB+/RUgPlAACI+yHrUKqUsm4zlpGV/Q8tEUx0Q4='

ค่า hash สำหรับสไตล์อินไลน์

ใช้เทคนิคเดียวกันกับแท็ก <style> แบบอินไลน์ คำนวณค่า hash แล้วเพิ่มลงใน style-src วิธีนี้ดีกว่า 'unsafe-inline' สำหรับ CSS

โหมดรายงาน CSP

ใช้ Content-Security-Policy-Report-Only เพื่อทดสอบนโยบายโดยไม่บังคับใช้ ระบบจะรายงานการละเมิดไปยังจุดรับรายงานของคุณ แต่จะไม่บล็อกสิ่งใด เหมาะอย่างยิ่งสำหรับการทยอยนำ CSP มาใช้

Content-Security-Policy-Report-Only: 
  default-src 'self';
  report-uri /csp-violations

// /csp-violations receives POSTs like:
{
  "csp-report": {
    "document-uri": "https://example.com/",
    "violated-directive": "script-src 'self'",
    "blocked-uri": "https://evil.com/x.js"
  }
}

report-to (สมัยใหม่)

report-to + Reporting-Endpoints เป็นสิ่งทดแทน report-uri แบบสมัยใหม่ ใช้ข้อมูลเดียวกัน แต่มีโครงสร้างมากกว่า

Reporting-Endpoints: csp="/csp-reports"
Content-Security-Policy: script-src 'self'; report-to csp

การผสานรวมกับเฟรมเวิร์ก

Next.js: ตั้งค่า CSP ผ่าน middleware.ts หรือส่วนหัวใน next.config.js Nuxt: ใช้โมดูล nuxt-security Vite: กำหนดค่าส่วนหัวของเซิร์ฟเวอร์สำหรับการพัฒนา และกำหนดค่าส่วนหัวของการใช้งานจริงผ่านผู้ให้บริการโฮสต์ (Vercel, Netlify)

// next.config.js
module.exports = {
  async headers() {
    return [{
      source: '/(.*)',
      headers: [{
        key: 'Content-Security-Policy',
        value: "default-src 'self'; script-src 'self' 'strict-dynamic'"
      }]
    }];
  }
};

การทดสอบ CSP

เปิด DevTools → Console: การละเมิด CSP จะถูกบันทึกไว้ที่นั่น ใช้ https://csp-evaluator.withgoogle.com/ เพื่อประเมินนโยบายของคุณ เริ่มด้วยโหมดรายงานเท่านั้นในการใช้งานจริง แล้วจึงบังคับใช้หลังแก้ไขการละเมิดทั้งหมด

ตรวจสอบอย่างรวดเร็ว

เหตุใดการใส่ 'unsafe-inline' ในคำสั่ง script-src จึงถือเป็นจุดอ่อนของ CSP

สรุป: แนวทางปฏิบัติที่ดีที่สุดสำหรับ CSP

ตั้งค่าส่วนหัว Content-Security-Policy พร้อมคำสั่งแยกตามประเภททรัพยากร หลีกเลี่ยง 'unsafe-inline' โดยใช้ค่า nonce + 'strict-dynamic' หรือค่า hash ของ SHA กำหนด frame-ancestors 'none' (หรือ 'self') ทดสอบในโหมดรายงานเท่านั้นก่อน ส่งการละเมิดไปยัง /csp-violations (หรือใช้ report-to แบบสมัยใหม่) เฟรมเวิร์กรองรับ CSP ผ่าน middleware หรือส่วนหัวจากการกำหนดค่า

เริ่มต้นได้ฟรี

เรียนรู้ HTML ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
41
บทเรียน
163

คำถามที่พบบ่อย

บทเรียน “Content Security Policy: nonce และแฮช” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “Content Security Policy: nonce และแฮช” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Frontend Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “Content Security Policy: nonce และแฮช”

เขียน CSP ที่เข้มงวดด้วย nonce สำหรับสคริปต์อินไลน์ ใช้แฮชกับโค้ดที่รู้จัก และใช้ report-uri เพื่อตรวจสอบการละเมิดในระบบจริง คุณปฏิบัติ Frontend Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Frontend Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Frontend Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “Content Security Policy: nonce และแฮช” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Frontend Academy นี้ได้ไหม

ได้ บทเรียน Frontend Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การป้องกัน XSS: การเข้ารหัสเอาต์พุตและ CSP
  2. CSRF: คุกกี้และโทเค็น SameSite
  3. Content Security Policy: nonce และแฮช
  4. โฟลว์ OAuth จากฟรอนต์เอนด์
← กลับไปที่ Frontend Academy