Script für IP-Sperre - Ich find den Fehler nicht
Sven
- php
Hallo :-)
Ich hab ein Voting-Script geschrieben und habe Cookie-Schutz gewählt. (Man hat mehrere Optionen zur Auswahl, kann aber jede davon nur einmal bewerten).
Ich hatte mir das eingerichtet, dass die Zeit und die IP-Adresse geloggt wird und musste feststellen dass mehrmals schnell hintereinander die gleiche Option bewertet wurde. Daher möchte ich nun zusätzlich eine 24-stündige IP-Sperre einbauen.
Habe folgendes IP-Bann-Script geschrieben. Man trifft eine Auswahl, diese wird zur Kenntnis genommen und anschliessend wird die IP-Adresse mit dem Timestamp in die Datenbank eingetragen. Ist die IP bereits eingetragen, wird überprüft, ob sie schon länger als 24 Stunden drin ist... wenn Ja, wird sie wieder aus der Datenbank entfernt. Wenn nicht, bekommt der USer eine Nachricht, dass er schon gevoted hat.
Aber irgendwie funktioniert es nicht... ist der User erstmal gesperrt, bleibt er auch 24 Stunden später immernoch gesperrt. Und das sperren klappt auch nicht immer :-S
<form name="form1" method="post" action="">
<p>Bitte Auswahl treffen:<br>
<select name="option">
<option>Option 1</option>
<option>Option 2</option>
</select>
</p>
<p>
<input type="submit" name="Submit" value="Abschicken">
</p>
</form>
<?
include("sql.php"); // Verbindung zur DB herstellen
if($option) {
$zeit_aktuell = time();
$ipadresse = $_SERVER['REMOTE_ADDR'];
$abfrage = "SELECT ip FROM ipsperre WHERE option = '$option'";
$ergebnis = mysql_query($abfrage);
$num_rows = mysql_num_rows($ergebnis);
if($num_rows == 0) {
echo "Der User ist nicht gesperrt; Bewertung vornehmen und sperren";
$eintrag = "INSERT INTO ipsperre (ip, zeit, option) VALUES ('$ipadresse', $zeit_aktuell, '$option')";
$eintragen = mysql_query($eintrag);
} else {
while ($row = mysql_fetch_array ($ergebnis))
{
if($row[ip] == $_SERVER['REMOTE_ADDR']) {
$zeit = $zeit_aktuell - $row['zeit'];
$zeitfenster = 60 * 60 * 24;
if ($zeit >= $zeitfenster) {
echo "Der User ist bereits gesperrt";
} else {
echo "Die IP-Adresse ist älter als 24 Stunden - entfernen und User abstimmen lassen";
}
}}}} else {
echo "Es wurde keine Auswahl getroffen.";
}
?>
Hallo :-)
Hallo auch
Ich hab ein Voting-Script geschrieben und habe Cookie-Schutz gewählt. (Man hat mehrere Optionen zur Auswahl, kann aber jede davon nur einmal bewerten).
Ich hatte mir das eingerichtet, dass die Zeit und die IP-Adresse geloggt wird und musste feststellen dass mehrmals schnell hintereinander die gleiche Option bewertet wurde. Daher möchte ich nun zusätzlich eine 24-stündige IP-Sperre einbauen.
Habe folgendes IP-Bann-Script geschrieben. Man trifft eine Auswahl, diese wird zur Kenntnis genommen und anschliessend wird die IP-Adresse mit dem Timestamp in die Datenbank eingetragen. Ist die IP bereits eingetragen, wird überprüft, ob sie schon länger als 24 Stunden drin ist... wenn Ja, wird sie wieder aus der Datenbank entfernt. Wenn nicht, bekommt der USer eine Nachricht, dass er schon gevoted hat.
Aber irgendwie funktioniert es nicht... ist der User erstmal gesperrt, bleibt er auch 24 Stunden später immernoch gesperrt. Und das sperren klappt auch nicht immer :-S
Ich würde nicht überprüfen, ob die IP schon mal geschrieben wurde.
Ich habe auch gerade in der letzt so etwas gemacht.
http://ratnaweera.no-ip.com/~michael/Zaehler/Zaehler_IPSPERRE_Zeit_Datei.php
Meiner löscht aber die Dateien schon nach einer Stunde.
Überprüfe, alle Dateien, ob sie älter als 24h sind.
Warum?
Kommt die IP-Adresse nie mehr, und noch eine, dann hast du mit der Zeit tausende von Dateien, die du dann manuell löschen musst.
Gruss Michy
Hi Sven,
gerade seh ich Deine Nutzung von dieser IP-Sperre. Da is jetzt einiges falsch gelaufen. Ich hab jetzt kein Bock, alles zu kommentieren und hinterher gefällt irgendeinem Simpel wieder meine Ausdrucksweise nicht. (Bin etwas müde, sorry)
Ich paste Dir hier gerade mal kurz meine IP-Sperre. Die benutze ich innerhalb eines kleinen Counter-Skripts (Auszug) für Flash.
Ich versuch´s gleich mal ein bisschen anzupassen.
<?php
$host = "localhost";
$database = "counter";
$user = "USER";
$passwd = "PASSWORD";
if (!$counter_id) {
echo "ERROR: Die Vote-ID wurde nicht übergeben.";
die();
}
$conn = mysql_connect($host, $user, $passwd);
$db = mysql_select_db($database);
if ($option) {
## Alle IP´s löschen, die älter als 24 Stunden
$time = time();
$deltime = $time - (60*60*24);
$delstatement = "delete from votetemp where timestamp <='$deltime'";
$delexecute = mysql_query($delstatement);
## Auslesen der IP
$user_ip = "$REMOTE_ADDR";
trim($user_ip); //nicht vergessen !
## ist die IP in der Datenbank vorhanden?
$query2 = "select id from votetemp where IP = '$user_ip' AND vote_id = '$vote_id'";
$result2 = @mysql_query($query2);
$num = @mysql_num_rows($result2);
if ($num >= 2) {
for ($i=1; $i < $num; $i++) {
$id_temp = mysql_result($result2, $i, 'id');
$delstatement2 = "delete from votetemp where id ='$id_temp'";
$delexecute2 = mysql_query($delstatement2);
}
}
## Falls IP vorhanden, Fehlermeldung ausgeben.
if ($num) {
echo "Hey, Hansl. Nur ein Vote innerhalb 24 Stunden.";
}
## Falls nicht, IP ins Temp-Table schreiben und vote zählen.
else {
echo "Dein Vote wurde gezählt";
$query3 = "insert into countertemp (IP,timestamp,vote_id) VALUES ('$user_ip','$time','$vote_id')";
$result3 = mysql_query($query3);
}
}
?>
und weil´s so schön ist hier noch der MySQL-Dump *g*
CREATE TABLE countertemp
(
id
int(5) NOT NULL AUTO_INCREMENT,
timestamp
int(15) default NULL,
IP
varchar(20) default NULL,
vote\_id
int(5) default NULL,
PRIMARY KEY (id
)
) TYPE=MyISAM;
Viel Spaß damit, Lars
Halihallo thematrixhasyou
if ($option) {
## Alle IP´s löschen, die älter als 24 Stunden
Warum das Usertracking über 24 Stunden bei IP's wenig Sinn macht und mit hohen
Fehlerraten verbunden ist, steht ausführlich im </archiv/>.
Der nächste Abschnitt ist eigentlich unnötig *g* . Aber irgendwie hatte er
Sinn, weiss auch nicht mehr so richtig. Bei irgendjemandem kam es vor,
dass 2 Einträge mit der gleichen IP waren. deswegen das doppelt gemoppelte.
Es kann sogar sein, dass 10'000 Computer dieselbe IP zur selben Zeit "haben". Oder aber,
dass ein Computer innerhalb von 24 Stunden 10 IP's hat. _Das_ ist das Problem.
if ($num) {
echo "Hey, Hansl. Nur ein Vote innerhalb 24 Stunden. Oder ein anderer von ca. 10'000,
welche dieselbe IP haben...";
Da anscheinend sehr oft derartige IP-Sperren realisiert werden (über deren Sinn und
Unsinn schon sehr oft im Archiv diskutiert wurde), hier noch einige Anmerkungen, wie man
die Datenstruktur etwas effizienter aufbaut:
}
CREATE TABLEcountertemp
(
id
int(5) NOT NULL AUTO_INCREMENT,
Wenn schon INT und derart grosse Anzahlen an Einträgen, dann bitte INT(10), denn jede
Zahl, die über INT abgebildet werden kann, hat auch in 10 Stellen platz, nicht so in 5.
timestamp
int(15) default NULL,
Eine Timestamp soll _immer_ in einem SMALLINT(5) UNSIGNED gespeichert werden! - Alles
andere ist Platzverschwendung. Möglich wäre auch DATETIME, obwohl ein SMALLINT(5) für
diese Anwendung wohl effizienter zu handhaben ist.
IP
varchar(20) default NULL,
IP's haben maximal 15 Zeichen, also wenn, dann VARCHAR(15). Zudem halte ich hier VARCHAR
für eine Platz und Performanceverschwendung, besser wäre CHAR(15), da diese direkt in die
RecordData geschrieben wird und nicht extra variabler Platz dafür reserviert werden muss.
Zudem: Das Selektieren geht tausendmal schneller.
vote\_id
int(5) default NULL,
Gibt's echt bis zu 2^64 Votes? - Schön für dich, alles andere ist Platzverschwendung.
Verwende MEDIUM- oder SMALLINT.
Und wo, wo bitte sind die Indizies, welche die Abfragen derart verschnellern könnten? -
Das ist essenziell für diese Aufgabe!
http://www.mysql.com/doc/en/MySQL_indexes.html
Also, Index auf DATETIME, Index auf IP, Index auf vote_id.
Wenn man schon derart performancesensitiven Programme schreibt (bei jedem Zugriff in
mehreren tausend IP's sehen, ob der User schon gevoted hat), sollte man sich schon etwas
mehr Gedanken zur Datenstruktur (die Programmierung lasse ich jetzt mal weg) machen.
Desweiteren macht ID als Primary Key hier keinen Sinn. PRIMARY KEY (timestamp,IP) wäre
wesentlich intelligenter, da a) der Index dann schon implizit ist, b) kein Platz für
Index und Daten der ID verbraucht wird und c) sowieso nur auf timestamp und IP selektiert
wird und somit ID völlig nutzlos ist. Dass dann keine zwei Records zur gleichen timestamp
und IP gespeichert werden können ist klar, aber was wäre denn der Vorteil davon? - Also:
PRIMARY KEY ist timestamp und IP.
Meine positive Kritik zur Datenstuktur einer IP-Sperre.
Viele Grüsse
Philipp