Tất cả bài viết
POST webhook Laravel bỏ qua CSRF qua VerifyCsrfToken except, byte getContent được xác minh bằng hash_equals trên php artisan serve cục bộ.
LaravelPHPwebhook debugginglocal testing

Webhook Laravel: miễn CSRF, raw body và xác minh chữ ký

Laravel bật CSRF trên mọi web route. Nhà cung cấp webhook gửi POST không có session cookie hay CSRF token — bạn nhận 419 trước khi controller chạy. Giải pháp: miễn CSRF có chọn lọc và đọc raw body qua $request->getContent().

Miễn CSRF cho route webhook

Thêm URI vào mảng $except trong App\Http\Middleware\VerifyCsrfToken (Laravel 11+: middleware trong bootstrap/app.php):

protected $except = [
    'webhooks/stripe',
    'webhooks/*',
];

Chỉ miễn path server-to-server — không tắt CSRF toàn app.

Đọc raw body để xác minh chữ ký

Sau khi bỏ qua CSRF, đọc byte nguyên vẹn:

public function handle(Request $request)
{
    $payload = $request->getContent(); // raw string
    $signature = $request->header('Stripe-Signature', '');

    if (!$this->verifySignature($payload, $signature)) {
        return response('', 401);
    }

    $event = json_decode($payload, true, 512, JSON_THROW_ON_ERROR);
    $this->processEvent($event);
    return response('', 200);
}

Dùng getContent(), không dùng all() hay input() — helper Laravel không trả byte đã ký.

Xác minh chữ ký trước logic nghiệp vụ

Trích header, tính digest từ raw payload, so sánh bằng hash_equals. Sai trả 401. Xem hướng dẫn xác minh chữ ký.

Thiết lập tunnel

  1. Chạy Laravel: php artisan serve --port=8000.
  2. Terminal thứ hai: npx portpreview 8000.
  3. Dán URL tunnel + path vào dashboard.
  4. Với TrustProxies, tin header forwarded từ tunnel.
  5. Kích hoạt sự kiện thử.

Bẫy thường gặp

Đọc body hai lần

getContent() sau json() rỗng. Đọc một lần, xác minh, parse.

Thứ tự middleware

Middleware parse JSON trước controller làm đổi byte. Tách route webhook.

Retry và idempotency

Lưu event ID — xem mẫu retry và idempotency.

Đọc thêm

Đọc thêm về cơ bản về localhost tunnelinggỡ lỗi webhook cục bộ. Cơ chế chữ ký xem hướng dẫn xác minh chữ ký. Handler chống trùng lặp xem mẫu retry và idempotency. bắt đầu PortPreview miễn phí.

Câu hỏi thường gặp

Tại sao Laravel trả 419 trên POST webhook?
VerifyCsrfToken từ chối POST không có CSRF token. Thêm path webhook vào $except rồi xác minh chữ ký.
Dùng getContent() hay all() cho webhook?
Dùng getContent() để xác minh chữ ký. all() và input() trả dữ liệu đã parse, không phải byte đã ký.
Làm sao test webhook Laravel cục bộ?
Chạy php artisan serve, expose bằng npx portpreview, dán URL tunnel vào dashboard và kích hoạt sự kiện thử.