ESP32 HTTPS: Gọi API bảo mật với WiFiClientSecure

Lập trình ESP32 gọi API qua giao thức HTTPS

Trong bài này chúng ta sẽ học ESP32 HTTPS: cách cho ESP32 gọi một API qua giao thức HTTPS — phiên bản có mã hóa của HTTP. Ngày nay hầu hết API công khai (thời tiết, ngân hàng, mạng xã hội…) đều bắt buộc dùng HTTPS, nên đây là kỹ năng gần như không thể thiếu khi làm dự án IoT kết nối internet thật sự.

Đây là một bài thực hành trong Serie Lập trình ESP32 từ A tới Z, tiếp nối bài lấy dữ liệu thời tiết với ESP32 HTTP Client — lần này chuyển từ HTTP thường sang HTTPS có mã hóa.

HTTPS khác HTTP ở đâu?

HTTPS (HyperText Transfer Protocol Secure) về bản chất vẫn là giao thức HTTP quen thuộc, chỉ khác là toàn bộ dữ liệu trao đổi được mã hóa bằng TLS/SSL trước khi truyền đi. Nếu HTTP giống như gửi thư không phong bì — ai chặn được đường truyền cũng đọc được nội dung — thì HTTPS giống như thư được niêm phong trong phong bì khóa kín, chỉ người nhận đúng mới mở ra đọc được.

  • HTTP mặc định chạy ở cổng 80, HTTPS mặc định chạy ở cổng 443.
  • HTTPS cần “bắt tay” (handshake) trao đổi khóa mã hóa trước khi truyền dữ liệu thật, nên tốn thêm chút thời gian và bộ nhớ so với HTTP — với ESP32 (bộ nhớ hạn chế) đây là điều cần lưu ý.

Lập trình ESP32 HTTPS gọi API

Kết nối WiFi

Phần kết nối WiFi giống hệt các bài trước, dùng WiFi.begin(ssid, password) rồi chờ WiFi.status() == WL_CONNECTED.

Dùng WiFiClientSecure thay vì WiFiClient thường

WiFiClientSecure client;
client.setInsecure(); // bo qua kiem tra chung chi SSL

HTTPClient https;
if (https.begin(client, apiUrl)) {
  int httpCode = https.GET();
  ...
}

Khác biệt mấu chốt so với bài HTTP thường: thay vì http.begin(url) với 1 tham số, ở đây phải dùng https.begin(client, apiUrl) với 2 tham số — tham số đầu là đối tượng WiFiClientSecure phụ trách phần mã hóa TLS, tham số sau mới là URL.

Lưu ý: client.setInsecure() bỏ qua hoàn toàn việc kiểm tra chứng chỉ SSL của server — nghĩa là ESP32 sẽ tin bất kỳ server nào tự xưng đúng tên miền, kể cả khi chứng chỉ giả mạo. Cách này chỉ nên dùng khi học/test nhanh. Với sản phẩm thực tế, nên dùng client.setCACert(rootCACertificate) kèm đúng chứng chỉ gốc (root CA) của server — an toàn hơn nhưng cần cập nhật lại code mỗi khi chứng chỉ đó hết hạn (thường 1-2 năm), nếu quên cập nhật thiết bị sẽ đột nhiên không gọi API được nữa dù code không đổi gì cả.

Code đầy đủ

#include <Arduino.h>

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>

const char* ssid = "Ten_Wifi_Cua_Ban";
const char* password = "Mat_Khau_Wifi";

const char* apiUrl = "https://jsonplaceholder.typicode.com/todos/1";

void setup() {
  Serial.begin(115200);

  Serial.print("Connecting to wifi ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    WiFiClientSecure client;
    client.setInsecure();

    HTTPClient https;
    Serial.println("Dang goi API qua HTTPS...");

    if (https.begin(client, apiUrl)) {
      int httpCode = https.GET();

      if (httpCode > 0) {
        Serial.print("Ma phan hoi: ");
        Serial.println(httpCode);
        String payload = https.getString();
        Serial.println("Noi dung tra ve:");
        Serial.println(payload);
      } else {
        Serial.print("Loi khi goi HTTPS: ");
        Serial.println(https.errorToString(httpCode));
      }
      https.end();
    } else {
      Serial.println("Khong the ket noi toi server HTTPS");
    }
  }

  delay(10000);
}

Mình dùng https://jsonplaceholder.typicode.com/todos/1 — 1 API test công khai, không cần đăng ký tài khoản hay API key, luôn trả về đúng 1 JSON cố định, rất tiện để test nhanh mà không vướng thủ tục xin key như Openweather.

Code đầy đủ mình để trên GitHub, các bạn xem tại 04-Protocol/04_HTTPS nhé.

Kết quả

Mở Serial Monitor ở baudrate 115200, sau khi ESP32 kết nối WiFi xong, cứ mỗi 10 giây các bạn sẽ thấy 1 lần gọi API mới, in ra mã phản hồi (200 là thành công) và nội dung JSON trả về.

Log Serial Monitor ESP32 HTTPS gọi API, mã phản hồi 200 và nội dung JSON trả về

Nếu gặp lỗi kết nối, thử kiểm tra lại ESP32 đã lấy được thời gian thực chưa — một số thư viện TLS cần đồng hồ hệ thống đúng để kiểm tra hạn chứng chỉ, dù setInsecure() đã bỏ qua bước này nên thường không gặp vấn đề, đúng không nào.

Kết

HTTPS là yêu cầu bắt buộc khi làm việc với hầu hết API công khai hiện nay — Openweather, Telegram Bot API, Google Sheets API… đều chỉ chấp nhận HTTPS chứ không cho gọi qua HTTP thường nữa. Nắm được cách dùng WiFiClientSecure sẽ mở khóa được rất nhiều dịch vụ online cho các dự án ESP32 của bạn.

Nếu thấy bài viết có ích, hãy chia sẻ cho bạn bè cùng học. Có thắc mắc gì cứ để lại bình luận, mình sẽ giải đáp nhé!

Rate this post

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *