การตรวจสอบลายเซ็น Webhook: วิธีรักษาความปลอดภัยการเชื่อมต่อของคุณ

Ashley Innocent

Ashley Innocent

22 December 2025

การตรวจสอบลายเซ็น Webhook: วิธีรักษาความปลอดภัยการเชื่อมต่อของคุณ

Webhooks เป็นหนึ่งในวิธีที่ทรงพลังที่สุดในการรับการอัปเดตแบบเรียลไทม์จากบริการภายนอก การส่ง HTTP POST เพียงครั้งเดียวจาก Stripe, GitHub, Shopify หรือ Twilio สามารถกระตุ้นตรรกะทางธุรกิจที่สำคัญในแอปพลิเคชันของคุณได้ เช่น การเรียกเก็บเงินจากลูกค้า, การอัปเดตที่เก็บข้อมูล (repository), การจัดส่งคำสั่งซื้อ หรือการส่ง SMS ยืนยัน

แต่คำขอ webhook ทุกรายการจะถูกส่งผ่านอินเทอร์เน็ตสาธารณะ และนั่นหมายความว่าใครก็ตามที่เดาหรือค้นพบ URL webhook ของคุณสามารถส่งเพย์โหลดที่เป็นอันตรายซึ่งดูเหมือนถูกต้องทุกประการได้ หากไม่มีการรับรองความถูกต้องที่เหมาะสม แอปพลิเคชันของคุณจะไม่มีทางแยกความแตกต่างระหว่างเหตุการณ์จริงและเหตุการณ์ปลอมได้

นี่คือจุดที่ การยืนยันลายเซ็น webhook เข้ามามีบทบาท เป็นกลไกที่เรียบง่ายและเป็นมาตรฐานที่ช่วยให้มั่นใจว่าคำขอ webhook ขาเข้าทุกรายการมาจากบริการที่คุณคาดหวังอย่างแท้จริง และไม่ได้รับการเปลี่ยนแปลงระหว่างการส่ง

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

💡
ก่อนที่เราจะลงลึกในรายละเอียดทางเทคนิค ผมอยากให้คุณมั่นใจว่าคุณมีเครื่องมือที่เหมาะสมในการตรวจสอบและดีบัก webhooks ได้ในไม่กี่นาที Apidog นั้นดาวน์โหลดฟรีและมีคุณสมบัติการทดสอบการยืนยันลายเซ็น webhook, ม็อกเซิร์ฟเวอร์ และการตรวจสอบเพย์โหลดแบบเรียลไทม์ในตัว — ไม่ต้องใช้บัตรเครดิต เป็นวิธีที่เร็วที่สุดในการยืนยันว่าตรรกะการตรวจสอบของคุณทำงานได้จริง
ปุ่ม

การยืนยันลายเซ็น Webhook คืออะไร?

การยืนยันลายเซ็น Webhook คือกระบวนการยืนยันว่าคำขอ webhook ขาเข้ามาจากบริการที่คุณคาดหวังจริง และไม่ได้รับการดัดแปลง

ผู้ให้บริการส่วนใหญ่ใช้ HMAC (Hash-based Message Authentication Code) ร่วมกับ SHA-256 หรือ SHA-512 บริการจะคำนวณ:

signature = HMAC-SHA256(secret_key, payload)

จากนั้นพวกเขาจะส่งลายเซ็นในส่วนหัว (โดยปกติคือ X-Signature, Signature หรือ X-Hub-Signature-256)

เซิร์ฟเวอร์ของคุณ:

  1. รับเพย์โหลดเป็นไบต์ดิบ (สำคัญมาก!)
  2. คำนวณ HMAC ใหม่โดยใช้ข้อมูลลับที่คุณเก็บไว้
  3. เปรียบเทียบลายเซ็นที่คำนวณได้กับลายเซ็นที่ได้รับ

หากตรงกันทั้งหมด คุณจะดำเนินการ webhook ต่อไป หากไม่ตรงกัน คุณจะส่งคืน HTTP 401 หรือ 403

เหตุใด HMAC-SHA256 จึงเป็นมาตรฐานอุตสาหกรรม

ผู้ให้บริการเลือกใช้ HMAC-SHA256 ด้วยเหตุผลที่ดี:

GitHub, Stripe, Shopify, Slack และบริการอื่นๆ อีกมากมาย ล้วนใช้ HMAC-SHA256

วิธีนำการยืนยันลายเซ็น Webhook ไปใช้งานใน Node.js

มาเริ่มต้นด้วยตัวอย่างจริงใน Node.js กัน

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const computedSignature = hmac.update(payload).digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(computedSignature),
    Buffer.from(signature)
  );
}

ประเด็นสำคัญที่ควรทราบ:

ตัวอย่าง Express middleware:

app.post('/webhooks/stripe', (req, res, next) => {
  const signature = req.headers['stripe-signature'];
  const secret = process.env.STRIPE_WEBHOOK_SECRET;

  // Get raw body (Express needs middleware to preserve raw body)
  const rawBody = req.rawBody || req.body; // use body-parser with verify option

  if (!verifyWebhookSignature(rawBody, signature, secret)) {
    return res.status(401).send('Invalid signature');
  }

  // Signature is valid → process the event
  next();
});

การใช้งานใน Python (FastAPI + Pydantic)

from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib

app = FastAPI()

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    computed = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(computed, signature)

@app.post("/webhooks/github")
async def github_webhook(request: Request):
    signature = request.headers.get("X-Hub-Signature-256")
    if not signature:
        raise HTTPException(status_code=401, detail="Missing signature")

    payload = await request.body()

    if not verify_signature(payload, signature.split('=')[1], SECRET):
        raise HTTPException(status_code=401, detail="Invalid signature")

    # Process webhook
    return {"status": "ok"}

ข้อผิดพลาดทั่วไปที่นักพัฒนาทำ (และวิธีหลีกเลี่ยง)

1. การใช้ JSON.stringify() หรือ Parsed Body

เฟรมเวิร์กจำนวนมากแยกวิเคราะห์ JSON โดยอัตโนมัติ ซึ่งทำให้การตรวจสอบล้มเหลวเนื่องจากช่องว่าง ลำดับคีย์ และรูปแบบที่แตกต่างกัน

วิธีแก้ไข: ควรดึงข้อมูล Body ดิบเสมอก่อนที่จะทำการแยกวิเคราะห์

ใน Express: ใช้ body-parser โดยมี { verify: true }

ใน FastAPI: ใช้ await request.body()

2. การเปรียบเทียบสตริงด้วย ===

การโจมตีแบบ Timing Attack สามารถเปิดเผยข้อมูลได้ ควรใช้ crypto.timingSafeEqual หรือ hmac.compare_digest

3. การเก็บความลับไว้ในโค้ด

ใช้ตัวแปรสภาพแวดล้อม (environment variables) หรือตัวจัดการความลับ (secret managers) (เช่น AWS Secrets Manager, HashiCorp Vault ฯลฯ)

4. การลืมจัดการกับการโจมตีแบบ Replay Attacks

ผู้ให้บริการส่วนใหญ่จะรวม timestamp ไว้ด้วย ตรวจสอบว่าเหตุการณ์นั้นเป็นเหตุการณ์ล่าสุด (เช่น ภายใน 5 นาที)

const timestamp = req.headers['X-Signature-Timestamp'];
if (Date.now() - timestamp > 5 * 60 * 1000) {
  return res.status(401).send('Timestamp too old');
}

5. การใช้ SHA-1 (ยังคงเกิดขึ้น!)

GitHub ได้เลิกใช้ SHA-1 ไปแล้วในปี 2022 ควรใช้ SHA-256 เสมอ

การทดสอบการยืนยันลายเซ็น Webhook ด้วย Apidog

การทดสอบ webhooks ด้วยตนเองนั้นเป็นเรื่องที่ยุ่งยาก คุณจะต้องส่งคำขอ ตรวจสอบบันทึก แก้ไข แล้วทำซ้ำ

Apidog ทำให้เรื่องนี้ง่ายดาย:

ในโปรเจกต์ Apidog ของคุณ ให้คลิกไอคอน + ที่แถบด้านข้างซ้าย แล้วเลือก "New Other Protocol APls" > "Webhook"

CleanShot 2025-11-05 at 17.18.02@2x.png

หลังจากสร้าง Webhook แล้ว ให้กรอกข้อมูลในช่องต่อไปนี้ใน editor:Request Method: โดยทั่วไปคือPOST.Webhook name: ชื่อนี้จะปรากฏในเอกสาร API และการส่งออก OpenAPI เช่น order.Debug URL(optional): URL จริงที่ใช้สำหรับการส่งคำขอทดสอบ หมายเหตุ: นี่ใช้เพื่อการทดสอบเท่านั้นและจะไม่รวมอยู่ในเอกสาร.Other Info: เช่น body ของคำขอ

image.png

คลิกบันทึกเมื่อคุณกรอกข้อมูลในช่องที่จำเป็นทั้งหมดแล้ว เพียงป้อน URL Webhook ของคุณลงในช่อง Debug URL จากนั้นคลิก Send เพื่อจำลองการเรียก Webhook

image.png

ฉันประหยัดเวลาในการดีบักไปได้หลายชั่วโมงด้วย Webhook simulator ของ Apidog มันยังรองรับรูปแบบ stripe-signature ที่แน่นอนของ Stripe และคำนำหน้า sha256=... ของ GitHub อีกด้วย

ตัวอย่างจริง: การยืนยัน Webhooks ของ Stripe

Stripe ใช้รูปแบบส่วนหัวพิเศษ:

stripe-signature: t=1681234567,v1=abc123...,v0=def456...

คุณต้อง:

Stripe มีไลบรารีอย่างเป็นทางการเพื่อจัดการความซับซ้อนนี้:

const stripe = require('stripe')('sk_...');
stripe.webhooks.constructEvent(payload, sigHeader, endpointSecret);

แต่การทำความเข้าใจ HMAC ที่อยู่เบื้องหลังเป็นสิ่งสำคัญเมื่อคุณต้องนำไปใช้งานเอง

หัวข้อขั้นสูง: การรองรับลายเซ็นหลายแบบ

ผู้ให้บริการบางราย (เช่น Stripe) ส่งลายเซ็นหลายแบบเพื่อความเข้ากันได้แบบย้อนหลัง โค้ดของคุณควร:

แนวทางปฏิบัติที่ดีที่สุดด้านความปลอดภัยในปี 2025

สรุป: ขั้นตอนการยืนยันเล็กน้อย, ผลประโยชน์ด้านความปลอดภัยที่ยิ่งใหญ่

การยืนยันลายเซ็น Webhook อาจดูเหมือนเป็นรายละเอียดเล็กน้อย แต่มันคือความแตกต่างระหว่างแอปพลิเคชันที่ปลอดภัยกับแอปพลิเคชันที่ผู้โจมตีสามารถใช้ประโยชน์ได้อย่างง่ายดาย

นำไปใช้งานอย่างถูกต้อง ทดสอบอย่างละเอียดด้วยเครื่องมือเช่น Apidog และนอนหลับสบายใจได้เมื่อรู้ว่าการเชื่อมต่อของคุณได้รับการปกป้อง

ดาวน์โหลด Apidog ฟรีวันนี้ และยืนยัน webhook แรกของคุณได้ภายใน 5 นาที เป็นวิธีที่เร็วที่สุดในการพิสูจน์ว่าโค้ดของคุณใช้งานได้จริง

ปุ่ม

ฝึกการออกแบบ API แบบ Design-first ใน Apidog

ค้นพบวิธีที่ง่ายขึ้นในการสร้างและใช้ API