Wartezeit ausrechnen, wie lange der User sich nicht einloggen darf, wenn er max. 5 Fehlversuche in 5 Minuten haben darf

  • PHP

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Marcus Gräfe.

    Wartezeit ausrechnen, wie lange der User sich nicht einloggen darf, wenn er max. 5 Fehlversuche in 5 Minuten haben darf

    Vielleicht bin ich für heute schon zu müde, oder aber es gibt dafür keine so einfache Lösung, wie ich mir das wünsche. Ich habe einen Login in PHP 8 gebaut. In einer MariaDB-Datenbank wird geprüft, ob der User innerhalb der letzten 5 Minuten 5 oder mehr Fehlversuche beim Login hatte. Falls ja, so bekommt er einen Fehler. Als zusätzlichen "Service" möchte ich ihm anzeigen, wie lange er warten muss (in Sekunden), damit diese Bedingungen nicht mehr erfüllt sind.

    Das hier ist erst mal der Code:

    PHP-Quellcode

    1. $result = $db->query('SELECT COUNT(*), MAX(accesstime) FROM user_accesslog WHERE success = FALSE AND accesstime >= ' . time() - (5 * 60)); // letzte 5 Minuten
    2. $row = $db->fetch_row();
    3. if ($row[0] >= 5) {
    4. // User muss warten vor nächstem Login
    5. die('Password has been entered wrong too often, please wait ' . '...' . ' seconds.');
    6. }

    In das '...' soll die Zeit rein. Im Moment zur Verfügung stehen die Werte $row[1] für den letzten fehlerhaften Zugriffszeitpunkt (könnte man auch auf den ältesten innerhalb der letzten 5 Minuten setzen), die aktuelle Zeit time() und natürlich der Wert 5 für die 5 Minuten Wartezeit.

    Hat jemand einen Ansatz?
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum
    Ich glaube, dass eure beiden Rechnungen nicht korrekt sind. Hier mal ein Beispiel:

    1 13:10:01
    2 13:11:05
    3 13:12:01
    4 13:13:01
    5 13:13:02
    6 13:14:01

    Aktuelle Zeit: 13:15:01
    Fehlversuche in den letzte 5 Minuten: 6
    Fragestellung: Ab wann reduziert sich die 6 auf 4?

    Rechne ich à la @slice so kommt bei 13:15:01 + 5 Min - 13:14:01 = 6 Minuten raus. Das kann natürlich nicht sein, kann ja max. 5 sein.

    Bei @Fakiz kommt 13:10:01 + 5 Min - 13:15:01 = 0 raus. Kann auch nicht sein, weil ich muss ja warten.
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum
    Wie wäre es damit?

    SQL-Abfrage

    1. select TIMESTAMPADD(MINUTE, 5, MIN(accesstime)) from (select accesstime from user_accesslog where success = false order by accesstime desc limit 5) t;
    Mit freundlichen Grüßen,
    Thunderbolt
    Ist sicher nicht die schönste Lösung, aber mit MySQL/MariaDB sollte es so klappen (Pseudo-Code):

    Quellcode

    1. $maxAttempts = 5;
    2. $timeframe = 5*60;
    3. SELECT MIN(last_failed_attempts.accesstime) + ${timeframe}
    4. FROM (
    5. SELECT accesstime
    6. FROM user_accesslog
    7. WHERE success = FALSE
    8. AND accesstime >= time() - ${timeframe}
    9. ORDER BY accesstime DESC
    10. LIMIT ${maxAttempts - 1}
    11. ) last_failed_attempts


    PS: Durch gezieltes Falsch-anmelden kann man den Login leicht für alle Nutzer lahmlegen. Daher wäre, ja nach Service, weitere Maßnahmen wie Captcha, IP-Abfrage, etc. unter Umständen sinnvoll.
    Danke für eure Lösungen. Ich werde diese allerdings erst am Montag ausprobieren können. Ich melde mich dann.

    @3daycliff Bzgl. des Lahmlegens hast du natürlich Recht. Wie ich damit umgehe, weiß ich noch nicht. Captcha scheidet aber aus. Und die IP bringt bei echten Bruteforce-Attacken sowieso nichts, weil diese meist wild gewürfelt werden.
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum
    Ich habe es nun gelöst, wenn auch etwas anders als eure Tipps:

    PHP-Quellcode

    1. $result = $db->query('SELECT COUNT(*), MIN(accesstime) FROM user_accesslog WHERE success = FALSE AND accesstime >= ' . time() - (5 * 60)); // letzte 5 Minuten
    2. $row = $db->fetch_row();
    3. if ($row[0] >= 5) {
    4. // User muss warten vor nächstem Login
    5. die('Password has been entered wrong too often, please wait ' . abs(time() - ($row[1] + (5 * 60))) + 1 . ' seconds.');
    6. }

    Die Änderungen sind also:
    MIN statt MAX in der SQL-Anweisung und abs(time() - ($row[1] + (5 * 60))) + 1 zum Ausrechnen der Wartezeit.

    Danke für eure Antworten, hat mich auf jeden Fall etwas in die richtige Richtung gebracht (was nicht heißt, dass eure Lösungen nicht funktionieren (habe ich nicht exakt so getestet), finde meine aber etwas eleganter).

    EDIT: Jetzt, wo ich mir den Thread nochmal durchlese, stelle ich fest, dass die Lösung von @Fakiz vmtl. doch korrekt war. Da fehlte im Prinzip nur das +1. Da war die Rechnung zwar andersrum, aber dann spart man sich das abs.

    EDIT #2: Habe den Part in der PHP-Anweisung nun auf $row[1] + (5 * 60) - time() + 1 geändert. Ist logischer als mit dem "abs". Wenn ich jetzt nicht total auf dem Schlauch stehe, ist das die Lösung.

    EDIT #3: Vielleicht auch doch nicht ... Bei den meisten meiner Beispiele klappt es, aber nicht bei dem aus Post #5. Dann probiere ich mal weiter ... ;)

    EDIT #4 (hoffentlich der letzte): Nach ewigem Rumprobieren habe ich nun eine Lösung, denke ich zumindest:

    PHP-Quellcode

    1. $result = $db->query("SELECT COUNT(*), MIN(accesstime) FROM (SELECT accesstime FROM user_accesslog WHERE user_id = 1 AND success = FALSE AND accesstime >= " . time() - (5 * 60) . ' ORDER BY accesstime DESC LIMIT ' . 5 . ') u'); // Anzahl Versuche und letzten Zugriff im Zeitraum ermitteln
    2. $row = $db->fetch_row();
    3. if ($row[0] >= 5) {
    4. // User muss warten vor nächstem Login
    5. die('Password has been entered wrong too often, please wait ' . $row[1] + (5 * 60) - time() + 1 . ' seconds.');
    6. }

    Das ist im Prinzip ein Mix aus allen Tipps hier im Thread. Wobei ich glaube, dass die Lösung von @3daycliff am nächsten an meiner finalen Lösung dran ist.
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum

    Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von „Marcus Gräfe“ ()