0

Series PHP cURL Extension | Bài 3: Xác thực (Authentication), Xử lý SSL và Tuyệt chiêu Debug

Chào anh em, trải qua 2 bài đầu tiên của series, chúng ta đã có thể thoải mái kéo (GET) và đẩy (POST) dữ liệu đi khắp nơi. Nhưng trong môi trường thực tế, không có một hệ thống nào mở toang cánh cửa để ai cũng có thể chọc vào. Các API nghiêm túc (như hệ thống bán vé, cổng thanh toán, hay microservices nội bộ) đều yêu cầu "thẻ căn cước" – tức là quá trình Xác thực (Authentication).

Hôm nay, ở Bài 3, chúng ta sẽ học cách trang bị "thẻ căn cước" cho cURL request, cách xử lý những lỗi liên quan đến bảo mật SSL (đặc biệt là khi code ở môi trường local), và quan trọng nhất: cách "bắt bệnh" cURL khi mọi thứ không chạy như ý muốn.

1. Vượt ải Xác thực (Authentication)

Tùy thuộc vào bên cung cấp API, họ sẽ yêu cầu các phương thức xác thực khác nhau. Dưới đây là 2 loại phổ biến nhất.

1.1. Basic Authentication

Phương pháp cổ điển này yêu cầu một cặp username:password. cURL hỗ trợ tận răng việc này thông qua một hằng số duy nhất: CURLOPT_USERPWD.

<?php
$ch = curl_init('https://api.example.com/secure-data');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Khai báo username và password cách nhau bởi dấu hai chấm (:)
curl_setopt($ch, CURLOPT_USERPWD, "admin:secret_password_123");

$response = curl_exec($ch);
curl_close($ch);
?>

Lưu ý: Khi dùng Basic Auth, bản chất cURL sẽ mã hóa chuỗi username:password ra Base64 và nhét vào Header. Do đó, bắt buộc API đích phải chạy trên HTTPS để tránh bị đánh cắp dữ liệu trên đường truyền.

1.2. Bearer Token (JWT / OAuth2)

Đây là tiêu chuẩn của các API hiện đại. Khi bạn đăng nhập thành công, server trả về một đoạn Token dài ngoằng (ví dụ: JSON Web Token - JWT). Ở các request sau, bạn phải đính kèm Token này vào HTTP Header.

<?php
$token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."; // Token lấy từ bước Login

$ch = curl_init('https://api.example.com/user/profile');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Nhét Token vào Header Authorization
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $token,
    'Accept: application/json'
]);

$response = curl_exec($ch);
curl_close($ch);
?>

2. Ám ảnh mang tên "SSL Certificate Problem"

Khi làm việc trên môi trường Local (XAMPP, Docker...) và gọi API ra ngoài HTTPS, 90% anh em từng khóc thét với lỗi: cURL error 60: SSL certificate problem: unable to get local issuer certificate.

Nguyên nhân là do máy tính của bạn không có hoặc không tìm thấy file chứa các chứng chỉ gốc (CA Certificates) để xác minh tính hợp lệ của cái API bạn đang gọi.

Cách 1: Tắt kiểm tra SSL (Chỉ dùng cho Local/Test)

Đây là cách "chữa cháy" nhanh nhất nhưng tuyệt đối không mang lên Production vì nó khiến hệ thống của bạn dễ bị tấn công Man-in-the-Middle (MitM).

// Tắt kiểm tra chứng chỉ của server đích
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Tắt kiểm tra xem tên miền có khớp với chứng chỉ không
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

Cách 2: Chuẩn men Backend (Dành cho Production)

Cách đúng đắn là tải file cacert.pem (chứa danh sách chứng chỉ gốc) từ trang chủ curl (curl.se/ca/cacert.pem) về máy chủ của bạn, sau đó trỏ cURL tới file đó:

// Đường dẫn tuyệt đối tới file cacert.pem trên server
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/certs/cacert.pem');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

3. Tuyệt chiêu Debug cURL khi mọi thứ "im lìm"

Gọi API không thấy báo lỗi, cũng không thấy data trả về, log trắng tinh. Làm sao để biết request đã bay đi đâu? Đã gửi đúng Header chưa?

Đừng đoán mò, hãy bật chế độ Verbose (lắm lời) của cURL lên. Nó sẽ in ra toàn bộ quá trình bắt tay (handshake), headers gửi đi và headers nhận về.

<?php
$ch = curl_init('https://httpbin.org/get');

// Mở một stream lưu trữ tạm thời trong bộ nhớ
$verboseLog = fopen('php://temp', 'w+');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Bật chế độ lắm lời
curl_setopt($ch, CURLOPT_VERBOSE, true);
// Trút toàn bộ log vào stream vừa tạo
curl_setopt($ch, CURLOPT_STDERR, $verboseLog);

curl_exec($ch);

// Đọc lại log để xem cURL đã làm những gì
rewind($verboseLog);
$debugInfo = stream_get_contents($verboseLog);

echo "<pre>Log Debug cURL:\n" . htmlspecialchars($debugInfo) . "</pre>";

curl_close($ch);
?>

Bằng đoạn code này, mọi uẩn khúc từ việc API redirect (mã 301, 302) đi đâu, hay bạn gửi thiếu Header gì, đều phơi bày rõ ràng như ban ngày.

Tổng kết Bài 3

Hiểu và làm chủ được Xác thực, SSL và kỹ năng Debug chính là ranh giới giữa một thợ gõ code và một Backend Engineer thực thụ.

Ở Bài 4 (và cũng là bài cuối của series), chúng ta sẽ chạm tay vào một kỹ thuật cực kỳ hóc búa nhưng mang lại hiệu năng đột phá: cURL Multi – Xử lý các request bất đồng bộ (Asynchronous) để tối ưu thời gian phản hồi của hệ thống. Hẹn anh em ở bài sau!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí