Bietet Rezepte, Lösungen und ausführliche Beispiele rund um gesundes SQL und zufriedene Datenbanken.
Immer wieder gibt es die Anforderung eine bestimmte IP-Adresse eine zeitlang zu sperren. Beispielsweise bei Tippspielen oder ähnlichem. Wie läßt sich so etwas einfach realisieren? Das folgende Beispiel zeigt eine mögliche Lösung. Da hierbei spezielle MySQL SQL-Befehle genutzt werden, ist die Abfrage nicht unmittelbar auf andere Datenbanken portierbar. Aber prinzipiell stellen auch andere Datenbanken ähnliche Zeitberechnungen zur Verfügung.
* MySQL 5.1.30
Die Datenbank-Tabelle hierfür sieht wie folgt aus. Damit die Abfrage später schnell genug ist, benötigen wir auch einen passenden Index.
/**
* Log-Tabelle mit den IP-Adressen
*/
CREATE TABLE ip_sperre (
ip VARCHAR(60) NOT NULL,
zeit TIMESTAMP NOT NULL
);
CREATE INDEX sx_ip_sperre_01 ON ip_sperre ( ip, zeit);
Kommt ein Benutzer (mit z. B. der IP 255.255.255.254 ) auf die Seite, wird zuerst seine IP geprüft. Gibt es zu dieser IP bereits einen Eintrag, der jünger als 1 Stunde ist, liefert die Abfrage ein Ergebnis. Existiert kein Eintrag innerhalb der letzten Stunde, liefert die Abfrage als Ergebnis die Ziffer 0.
SELECT COUNT(*) AS sperre
FROM ip_sperre
WHERE ip = '255.255.255.254'
GROUP BY ip
HAVING MAX(zeit) >= SUBTIME(current_timestamp,'01:00:00.000000');
Ist keine Sperre erforderlich, wird ein Datensatz mit dieser IP (z. B. 255.255.255.254 ) und einem aktuellen Zeitstempel eingefügt.
INSERT INTO ip_sperre
( ip, zeit ) VALUES
( '255.255.255.254', CURRENT_TIMESTAMP);
Für das nachfolgende Beispiel legen wir uns ein paar Testdaten an. Hierbei handelt es sich um drei verschiedene IP-Adressen mit jeweils eigenem Zeitstempel.
/**
* Einfügen von drei Testdatensätzen
*/
INSERT INTO ip_sperre
( ip, zeit ) VALUES
( '127.0.0.1', '2010-07-09 11:00:00.000000'),
( '127.0.0.2', '2010-07-09 12:30:00.000000'),
( '127.0.0.3', '2010-07-09 13:00:00.000000');
Und so läßt sich prüfen, welche IPs zum aktuellen Zeitpunkt (13:00 Uhr am 05.07.2010) gesperrt sind, also der neueste Eintrag vor weniger als einer Stunde erfolgt ist.
/**
* Alle gesperrten IPs laut Zeitstempel minus 1 Stunde suchen
*/
SELECT ip AS sperre
FROM ip_sperre
GROUP BY ip
HAVING MAX(zeit) >= SUBTIME('2010-07-09 13:00:00.000000','01:00:00.000000');
+-----------+
| sperre |
+-----------+
| 127.0.0.2 |
| 127.0.0.3 |
+-----------+
2 rows in set (0.08 sec)
Mit Hilfe eines GROUP BY über die Spalte IP und HAVING MAX(zeit) wird der neueste Eintrag zu jeder IP gefunden. Ist dieser neueste Zeiteintrag (siehe HAVING MAX(zeit)) dann aktueller als der berechnete Zeitwert von SUBSTIME(), dann läuft die Sperrzeit noch.
Der Funktion SUBTIME werden zwei Parameter übergeben. Zuerst die aktuelle Testzeit (05.07.2010 13:00 Uhr), sowie als zweiter Parameter die Zeitmenge (1 Stunde), die abgezogen werden soll.
So wird ermittelt, ob eine IP gesperrt ist.
/**
* Ermittelt ob eine IP noch gesperrt ist
* sperre => 0 (Nein) , => 1 (Ja)
*/
SELECT COUNT(*) AS sperre
FROM ip_sperre
WHERE ip = '127.0.0.1'
GROUP BY ip
HAVING MAX(zeit) >= SUBTIME('2010-07-09 13:00:00.000000','01:00:00.000000');
Empty set (0.01 sec)
mysql>
Als Ergebnis liefert MySQL Empty set. Die IP 127.0.0.1 ist demnach nicht mehr in der Zeitsperre. Dieser Benutzer darf sich wieder anmelden.
Hinweis: Da es verschiedenste Möglichkeiten gibt die IP zu manipulieren, ist eine alleinige Prüfung auf die IP nicht ausreichend, um die Manipulation einer Abstimmung zu verhindern.