Chủ đề

Xác thực HMAC

Xác thực HMAC là cách FastOG xác minh rằng mọi yêu cầu hình ảnh OG dựa trên đăng ký đều đến từ máy chủ của chính bạn — các URL đã ký giúp bảo vệ tín dụng của bạn. Đăng ký, sau đó chọn gói API Động (Dynamic API) và tạo khóa API cùng bí mật HMAC trong bảng điều khiển (dashboard); các lần hiển thị API trả phí đều sạch sẽ. Trang này bao gồm các quy tắc phía máy chủ đằng sau hình ảnh Open Graph động, từ việc ký chuỗi truy vấn chuẩn (canonical query signing) đến so sánh thời gian hằng số (constant-time comparison).

Tổng quan

Xác thực chữ ký HMAC-SHA256 đã được thêm vào endpoint /api/v1/og để ngăn chặn việc sử dụng hạn mức API trái phép. Điều này đảm bảo chỉ những yêu cầu từ trang web hợp lệ mới có thể tạo hình ảnh OG.

Kiến trúc

Xác thực hai lớp:

  1. Chữ ký HMAC (lớp đầu tiên) – Xác nhận yêu cầu đến từ nguồn đáng tin cậy (trang web)
  2. Khóa API (lớp thứ hai) – Xác định tài khoản người dùng để tính hạn mức kết xuất (render quota)

Một middleware duy nhất (ApiKeyAuth): xác minh chữ ký (tham số truy vấn) và phân giải khóa API để tính hạn mức kết xuất trong một lần xử lý — từ chối nhanh (fail fast) đối với chữ ký không hợp lệ.

Tham số truy vấn, không phải header: Vì hình ảnh OG được tải bởi trình thu thập dữ liệu của mạng xã hội (LinkedIn, Twitter, Facebook) không gửi header tùy chỉnh, chữ ký được truyền qua tham số truy vấn trong URL:

GET /api/v1/og?title=Hello&key=sk_quick_123abc&s=<hmac>

Triển khai

Các tệp đã tạo/sửa đổi

  • app/Http/Middleware/HmacSignature.php - Middleware mới xác thực chữ ký HMAC (tham số truy vấn)
  • routes/api.php - Thêm middleware HMAC vào tuyến OG
  • bootstrap/app.php - Đăng ký bí danh middleware hmac
  • app/Models/ApiKey.php - Thêm trường hmac_secret (bí mật riêng cho từng người dùng)
  • app/Http/Controllers/DashboardController.php - Tạo bí mật HMAC khi tạo khóa API
  • database/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php - Migration cho cột hmac_secret
  • resources/js/Pages/Dashboard/ApiKeys.svelte - Hiển thị bí mật HMAC cho người dùng (một lần)
  • docs/hmac-signature-guide.md - Hướng dẫn triển khai phía máy khách
  • tests/Feature/HmacSignatureTest.php - 8 bài kiểm thử đạt yêu cầu

Thuật toán chữ ký

method = HTTP method (e.g., "GET")
path  = request path (e.g., "/api/v1/og")
query = the request's DECODED query params

canonical = every param except `s`, keys sorted (array values sorted too),
            each `key=value` RFC-3986 encoded (unreserved-only), joined with "&"
message   = method + "/" + path + "\n" + canonical
signature = HMAC-SHA256(message, hmac_secret)

Query parameters:
  key=<apiKey>
  s=<signature>
  (no timestamp)

key là một phần của truy vấn chuẩn, do đó chữ ký được gắn với khóa API. Thay đổi bất kỳ tham số nào (tiêu đề, mẫu, hình ảnh, …) hoặc chính khóa đó sẽ làm thay đổi chuẩn → chữ ký không khớp → 401 → không hiển thị, không tính hạn mức. Các tham số giống nhau → chữ ký giống nhau → URL giống nhau → có thể lưu cache ở biên vĩnh viễn, phát lại mà không tính hạn mức.

Các tính năng bảo mật

  • Chữ ký định địa chỉ nội dung - Bất kỳ thay đổi tham số nào → 401 → không hiển thị, không tính hạn mức (bản thân URL là bằng chứng)
  • Không có dấu thời gian - URL được nhúng trong HTML công khai và lưu cache vĩnh viễn; chúng phải tồn tại lâu hơn 5 phút
  • So sánh thời gian hằng số (hash_equals()) - Ngăn chặn tấn công timing
  • Khóa API trong thông điệp - Chữ ký được gắn với khóa; đổi khóa sẽ thất bại
  • Riêng theo đường dẫn - Chữ ký chỉ hợp lệ cho đường dẫn chính xác
  • Riêng theo phương thức - Chữ ký GET sẽ không hoạt động cho POST
  • Bí mật riêng cho từng người dùng - Mỗi khóa API có bí mật HMAC riêng, có thể thu hồi độc lập (xoay vòng = công tắc ngắt cho các URL bị rò rỉ)

Cấu hình

Tạo Secret (Tự động)

Secret HMAC được tạo tự động khi tạo khóa API trong bảng điều khiển (dashboard). Secret này chỉ được hiển thị một lần cùng với khóa API, sau đó không bao giờ hiển thị lại.

Tạo thủ công (nếu cần):

bash
openssl rand -hex 32

Lược đồ cơ sở dữ liệu

sql
ALTER TABLE api_keys ADD COLUMN hmac_secret VARCHAR(64)
  COMMENT 'HMAC-SHA256 secret for signing OG image URLs (hex, 64 chars)';

Biến môi trường

Không cần biến môi trường toàn cục - secret được lưu trữ riêng cho từng người dùng trong bảng api_keys.

Ví dụ sử dụng (Backend của trang web)

javascript
// Node.js example - generate signed OG image URL
const crypto = require("crypto");

// RFC-3986 encode (encodeURIComponent leaves !'()* unencoded).
const enc = (s) =>
    encodeURIComponent(s).replace(
        /[!'()*]/g,
        (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase(),
    );

function generateOgImageUrl(baseUrl, params, apiKey, hmacSecret) {
    const all = { ...params, key: apiKey };

    // Canonical: every param (except s), sorted, RFC-3986 encoded, joined with "&".
    const pairs = [];
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? [...v].sort() : [v])
            pairs.push(`${enc(k)}=${enc(vv)}`);
    }
    pairs.sort();
    const canonical = pairs.join("&");

    const message = `GET/api/v1/og\n${canonical}`;
    const signature = crypto
        .createHmac("sha256", hmacSecret)
        .update(message)
        .digest("hex");

    const url = new URL(baseUrl);
    for (const [k, v] of Object.entries(all)) {
        const isArray = Array.isArray(v);
        for (const vv of isArray ? v : [v])
            url.searchParams.append(isArray ? `${k}[]` : k, vv);
    }
    url.searchParams.set("s", signature);
    return url.toString();
}

// Usage in meta tag
const ogUrl = generateOgImageUrl(
    "https://fastog.com/api/v1/og",
    { title: "Como criar um SaaS", template: "blog" },
    "sk_quick_123abc",
    process.env.HMAC_SECRET,
);

// <meta property="og:image" content="{ogUrl}" />

Phản hồi lỗi

Trạng thái Mã Mô tả
401 missing_signature Thiếu tham số truy vấn key hoặc s
401 invalid_signature Chữ ký không khớp với truy vấn chuẩn (bị can thiệp hoặc sai bí mật)

Kiểm thử

Chạy các bài kiểm thử:

bash
php artisan test --filter HmacSignatureTest

Tất cả 8 bài kiểm thử đều vượt qua:

  • ✅ Yêu cầu không có chữ ký bị từ chối
  • ✅ Yêu cầu thiếu tham số khóa bị từ chối
  • ✅ Tham số nội dung bị thay đổi (tiêu đề bị sửa) bị từ chối
  • ✅ Tham số được thêm vào bị từ chối
  • ✅ Chữ ký không hợp lệ bị từ chối
  • ✅ Chữ ký hợp lệ vượt qua kiểm tra HMAC
  • ✅ Chữ ký cụ thể theo đường dẫn
  • ✅ Chữ ký cụ thể theo phương thức
  • ✅ Các khóa API khác nhau có bí mật khác nhau

Tác động đến hiệu suất

  • Không đáng kể - Việc tính toán HMAC-SHA256 chỉ mất khoảng 0,1ms cho mỗi yêu cầu
  • Không có thêm lệnh gọi mạng nào - Việc xác thực được thực hiện cục bộ
  • Thất bại nhanh - Chữ ký không hợp lệ bị từ chối trước khi tra cứu khóa API

Các lưu ý về bảo mật

  1. Không bao giờ để lộ bí mật trong mã phía máy khách - Chỉ ký trên máy chủ
  2. Sử dụng HTTPS - HMAC bảo vệ chống lại các yêu cầu trái phép, HTTPS bảo vệ chống lại tấn công trung gian (MITM)
  3. Định kỳ xoay vòng bí mật - Đặc biệt nếu bị xâm phạm (yêu cầu tạo lại khóa API)
  4. Giám sát các chữ ký thất bại - Các lần thất bại lặp lại có thể cho thấy các cuộc tấn công
  5. Cô lập theo từng người dùng - Mỗi khóa API có bí mật HMAC riêng, việc xâm phạm một khóa không ảnh hưởng đến các khóa khác

Tài liệu tham khảo

Tài liệu tham khảo API đầy đủ

Dùng thử miễn phí — không cần đăng ký

Xem trước và kiểm tra hình ảnh OG động trong vài giây.

Mở Trình kiểm tra hình ảnh OG miễn phí

A BeCaSimulations site