PHP: Link-Aufruf nach Zeit ungültig

edit | delete

Autor: Ralf v.d.Mark

eingetragen: Mittwoch, 29. Januar 2025 um 16:56 Uhr (5/2025 Kalenderwoche)

geändert: Donnerstag, 20. Februar 2025 um 14:13 Uhr (8/2025 Kalenderwoche)

Keywords: Link Aufruf Zeit ungültig verfallen ablauf

Kategorien: PHP,

Text:

Wenn man über einen Link eine andere Webseite aufruft, aber dieser Aufruf nach einer gewissen Zeit nicht mehr funktioniert, also ungültig wird, kann man untenstehenden Quellcode benutzen.

Quellcode:  

<?php
/**
 * Das Script kann einen Link generieren, der auf der 
 * empfangenden Seite nach Zeit abläuft.
 * Zum Schutz wird der Schlüssel mit den Werten gehasht.
 *
 * PHP version 8.4
 *
 * @author     Ralf von der Mark (Vondy) <Ralf@vondy.de>
 * @copyright  2025, Vondy
 */


// Geheimer Schlüssel, serverseitig speichern! (identisch an beiden Stellen!)
define('SECRET_KEY', md5('GeheimSchluessel'
    . (((int)date('ydm')) * ((int)date('dym')) - ((int)date('ydm')))));

// Ablaufzeit für den temporären Link in Sekunden
define('SECRET_TIME_SEKUNDEN', 11);


/**
 * Funktion zum Generieren eines temporären Links
 *
 * @param string $baseUrl
 * @param array $data
 * @param int $validityInSeconds
 * @param string $secretKey
 * @return string
 */
function generateTemporaryLink(string $baseUrl, 
                               array $data, 
                               int $validityInSeconds,
                               string $secretKey): string
{
    $data['expires'] = time() + $validityInSeconds; // Ablaufzeit hinzufügen
    $data = array_map('strval', $data); // Alle Werte zu Strings konvertieren
    ksort($data); // Sortierung sicherstellen für konsistente JSON-Darstellung
    $signature = hash_hmac('sha256', json_encode($data), $secretKey); // Signatur erstellen
    $data['signature'] = $signature; // Signatur anhängen
    return $baseUrl . '?' . http_build_query($data); // URL erzeugen
}//ENDE: function generateTemporaryLink(...)

// Teil 1: Generierung eines temporären Links
$baseUrl = "/index.php"; // Ziel-URL der Aktion
$data = ['user_id' => 123, 'action' => 365, 'nochParams' => 'nixMehr'];// Parameter
$link = generateTemporaryLink(
            $baseUrl,
            $data,
            SECRET_TIME_SEKUNDEN,
            SECRET_KEY); // Link für 30 Sekunden
echo '<a href="' . htmlspecialchars($link) . '">'
        . urldecode(urldecode($link)) . '</a><hr>';

/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

//Seite 2 (Prüfende Seite) Teil 2: Validierung eines Aufrufs
if (!empty($_GET)) {

    /**
     * Funktion zum Überprüfen des Links und Ablauf der Zeit
     * @param array $query
     * @param string $secretKey
     * @return bool
     */
    function isValidRequest(array $query,
                            string $secretKey): bool
    {
        // Prüfen, ob die notwendigen Felder vorhanden sind
        if (!isset($query['expires'], $query['signature'])) {
            return false; // Ungültig, wenn erforderliche Felder fehlen
        }

        // Ablaufdatum prüfen
        if (time() > (int)$query['expires']) {
            return false; // Ungültig, wenn der Link abgelaufen ist
        }

        // Signatur extrahieren und entfernen (um sie neu berechnen zu können)
        $signature = $query['signature'];
        unset($query['signature']); // Signature-Feld entfernen

        // Alle Werte zu Strings konvertieren (sicherstellen, dass Typen gleich bleiben)
        $query = array_map('strval', $query);
        ksort($query);// Sicherstellen: selbe Reihenfolge wie beim Generieren

        // Signatur neu berechnen
        $calculatedSignature = hash_hmac('sha256', json_encode($query), $secretKey);

        // Signatur prüfen (timingsicher)
        return hash_equals($signature, $calculatedSignature);

    }//ENDE: function isValidRequest(...)

    // Geheimer Schlüssel SECRET_KEY (muss identisch zu dem beim Generieren sein)
    // GET-Parameter verarbeiten und überprüfen
    if (isValidRequest($_GET, SECRET_KEY)) {
        // Erfolg: Die Signatur ist gültig und der Link nicht abgelaufen
        echo '<br>
            <strong style="color: green;">
                Anfrage erfolgreich validiert. 
                Aktion wird ausgeführt!</strong>';
    } else {
        // Fehlerhafte oder manipulierte Anfrage
        http_response_code(403);
        echo '<br>
            <strong style="color: red;">
                Ungültiger oder abgelaufener Link.</strong>';
    }//ENDE: else => if (isValidRequest($_GET, SECRET_KEY))
}//ENDE: if (!empty($_GET))