Θέμα

Επικύρωση HMAC

Η επικύρωση HMAC είναι ο τρόπος με τον οποίο το FastOG επιβεβαιώνει ότι κάθε αίτημα για εικόνα OG βάσει συνδρομής προήλθε από τον δικό σας διακομιστή — οι υπογεγραμμένες διευθύνσεις URL διατηρούν τα πιστωτικά σας υπόλοιπα ασφαλή. Εγγραφείτε, επιλέξτε ένα πρόγραμμα Dynamic API και δημιουργήστε το κλειδί API και το μυστικό HMAC στον πίνακα ελέγχου (dashboard)· οι αποδόσεις μέσω πληρωμένου API είναι καθαρές. Αυτή η σελίδα καλύπτει τους κανόνες από την πλευρά του διακομιστή πίσω από τις δυναμικές εικόνες Open Graph, από την υπογραφή κανονικών ερωτημάτων έως τη σύγκριση σταθερού χρόνου.

Επισκόπηση

Η επαλήθευση υπογραφής HMAC-SHA256 έχει προστεθεί στο τελικό σημείο /api/v1/og για να αποτραπεί η μη εξουσιοδοτημένη χρήση του ορίου API. Αυτό διασφαλίζει ότι μόνο αιτήματα από τον νόμιμο ιστότοπο μπορούν να δημιουργούν εικόνες OG.

Αρχιτεκτονική

Αυθεντικοποίηση δύο επιπέδων:

  1. Υπογραφή HMAC (πρώτο επίπεδο) – Επικυρώνει ότι το αίτημα προέρχεται από αξιόπιστη πηγή (τον ιστότοπο)
  2. Κλειδί API (δεύτερο επίπεδο) – Ταυτοποιεί τον λογαριασμό χρήστη για τη χρέωση του ορίου απόδοσης (render-quota)

Ενιαίο middleware (ApiKeyAuth): επαληθεύει την υπογραφή (παράμετροι ερωτήματος) και αναλύει το κλειδί API για τη χρέωση του ορίου απόδοσης σε ένα πέρασμα — αποτυχία άμεση σε περίπτωση μη έγκυρης υπογραφής.

Παράμετροι ερωτήματος, όχι επικεφαλίδες: Επειδή οι εικόνες OG ανακτώνται από ανιχνευτές κοινωνικών δικτύων (LinkedIn, Twitter, Facebook) που δεν αποστέλλουν προσαρμοσμένες επικεφαλίδες, η υπογραφή μεταβιβάζεται μέσω παραμέτρων ερωτήματος στο URL:

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

Υλοποίηση

Αρχεία που Δημιουργήθηκαν/Τροποποιήθηκαν

  • app/Http/Middleware/HmacSignature.php - Νέο middleware που επικυρώνει υπογραφές HMAC (παράμετροι ερωτήματος)
  • routes/api.php - Προστέθηκε το middleware HMAC στη διαδρομή OG
  • bootstrap/app.php - Καταχωρήθηκε το ψευδώνυμο middleware hmac
  • app/Models/ApiKey.php - Προστέθηκε το πεδίο hmac_secret (μυστικά ανά χρήστη)
  • app/Http/Controllers/DashboardController.php - Δημιουργεί μυστικό HMAC κατά τη δημιουργία κλειδιού API
  • database/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php - Μετεγκατάσταση για τη στήλη hmac_secret
  • resources/js/Pages/Dashboard/ApiKeys.svelte - Εμφανίζει το μυστικό HMAC στον χρήστη (μία φορά)
  • docs/hmac-signature-guide.md - Οδηγός υλοποίησης για πελάτες
  • tests/Feature/HmacSignatureTest.php - 8 επιτυχή τεστ

Αλγόριθμος Υπογραφής

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 αποτελεί μέρος του κανονικού ερωτήματος, οπότε η υπογραφή δεσμεύεται στο κλειδί API. Η αλλαγή οποιασδήποτε παραμέτρου (τίτλος, πρότυπο, εικόνα, …) ή του ίδιου του κλειδιού αλλάζει το κανονικό ερώτημα → αναντιστοιχία υπογραφής → 401 → καμία απόδοση, καμία μέτρηση ορίου. Πανομοιότυπες παράμετροι → πανομοιότυπη υπογραφή → πανομοιότυπο URL → αποθηκεύσιμο στην άκρη για πάντα, αναπαραγόμενο χωρίς μέτρηση.

Χαρακτηριστικά Ασφαλείας

  • Υπογραφή με διεύθυνση περιεχομένου - Οποιαδήποτε αλλαγή παραμέτρου → 401 → καμία απόδοση, καμία μέτρηση ορίου (το ίδιο το URL αποτελεί την απόδειξη)
  • Χωρίς χρονική σήμανση - Τα URL ενσωματώνονται σε δημόσιο HTML και αποθηκεύονται στην κρυφή μνήμη για πάντα· πρέπει να επιβιώσουν πέρα από τα 5 λεπτά
  • Σύγκριση σταθερού χρόνου (hash_equals()) - Αποτρέπει επιθέσεις χρονισμού
  • Κλειδί API στο μήνυμα - Η υπογραφή δεσμεύεται στο κλειδί· η εναλλαγή κλειδιών αποτυγχάνει
  • Ειδική ανά διαδρομή - Η υπογραφή ισχύει μόνο για την ακριβή διαδρομή
  • Ειδική ανά μέθοδο - Η υπογραφή GET δεν θα λειτουργήσει για POST
  • Μυστικά ανά χρήστη - Κάθε κλειδί API έχει το δικό του μυστικό HMAC, το οποίο μπορεί να ανακληθεί ανεξάρτητα (περιστροφή = διακόπτης απενεργοποίησης για διαρρεύσαντα URL)

Διαμόρφωση

Δημιουργία Μυστικού Κλειδιού (Αυτόματη)

Το μυστικό κλειδί HMAC δημιουργείται αυτόματα κατά τη δημιουργία ενός κλειδιού API στον πίνακα ελέγχου (dashboard). Εμφανίζεται μία φορά μαζί με το κλειδί API και δεν εμφανίζεται ξανά.

Χειροκίνητη δημιουργία (αν χρειαστεί):

bash
openssl rand -hex 32

Σχήμα Βάσης Δεδομένων

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

Μεταβλητές Περιβάλλοντος

Δεν απαιτείται καμία καθολική μεταβλητή περιβάλλοντος - τα μυστικά κλειδιά αποθηκεύονται ανά χρήστη στον πίνακα api_keys.

Παράδειγμα Χρήσης (Backend Ιστοτόπου)

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}" />

Αποκρίσεις Σφαλμάτων

Κατάσταση Κωδικός Περιγραφή
401 missing_signature Λείπει η παράμετρος ερωτήματος key ή s
401 invalid_signature Η υπογραφή δεν ταιριάζει με το κανονικό ερώτημα (παραποιημένο ή λάθος μυστικό)

Δοκιμές

Εκτελέστε τις δοκιμές:

bash
php artisan test --filter HmacSignatureTest

Και οι 8 δοκιμές περνούν επιτυχώς:

  • ✅ Το αίτημα χωρίς υπογραφή απορρίπτεται
  • ✅ Το αίτημα με παραλειπόμενη παράμετρο κλειδιού απορρίπτεται
  • ✅ Το αίτημα με παραποιημένη παράμετρο περιεχομένου (αλλαγμένος τίτλος) απορρίπτεται
  • ✅ Η προστιθέμενη παράμετρος απορρίπτεται
  • ✅ Η μη έγκυρη υπογραφή απορρίπτεται
  • ✅ Η έγκυρη υπογραφή περνά τον έλεγχο HMAC
  • ✅ Η υπογραφή εξαρτάται από τη διαδρομή (path)
  • ✅ Η υπογραφή εξαρτάται από τη μέθοδο (method)
  • ✅ Διαφορετικά κλειδιά API έχουν διαφορετικά μυστικά

Επίδραση στην Απόδοση

  • Αμελητέα – Ο υπολογισμός HMAC-SHA256 διαρκεί περίπου 0,1 ms ανά αίτημα
  • Καμία επιπλέον κλήση δικτύου – Η επαλήθευση γίνεται τοπικά
  • Άμεση αποτυχία – Οι μη έγκυρες υπογραφές απορρίπτονται πριν από την αναζήτηση του κλειδιού API

Ζητήματα Ασφάλειας

  1. Ποτέ μην εκθέτετε το μυστικό σε κώδικα από την πλευρά του πελάτη - Υπογράφετε μόνο στον διακομιστή
  2. Χρησιμοποιήστε HTTPS - Το HMAC προστατεύει από μη εξουσιοδοτημένα αιτήματα, το HTTPS προστατεύει από επιθέσεις MITM
  3. Αλλάζετε περιοδικά τα μυστικά - Ειδικά αν έχουν παραβιαστεί (απαιτεί αναδημιουργία του κλειδιού API)
  4. Παρακολουθείτε τις αποτυχημένες υπογραφές - Οι επαναλαμβανόμενες αποτυχίες μπορεί να υποδηλώνουν επιθέσεις
  5. Απομόνωση ανά χρήστη - Κάθε κλειδί API έχει το δικό του μυστικό HMAC, η παραβίαση του ενός δεν επηρεάζει τα άλλα

Αναφορές

Πλήρης Αναφορά API

Δοκιμάστε το δωρεάν — δεν απαιτείται εγγραφή

Προεπισκόπηση και δοκιμή δυναμικών εικόνων OG σε δευτερόλεπτα.

Ανοίξτε τον Δωρεάν Ελεγκτή Εικόνων OG

A BeCaSimulations site