Thomas: Da ist der Wurm drin: if ($row !== false && password_verify

Hallo,

ich habe ein Problem in meinem Script zu meinem Zugansbereich.

	$statement = $pdo->prepare("SELECT * FROM member WHERE email = :email AND activ=1");
	$result = $statement->execute(array('email' => $email));
	$row = $statement->fetch();
	//Überprüfung des Passworts
	if ($row !== false && password_verify($passwort, $user['passwort'])) {

Es wird überprüft ob die Email vorhanden ist und ob der Account aktiv ist, anschließend wird das Passwort überprüft.

So weit theoretisch. Denn das Passwort wird auch dann überprüft, wenn bei activ eine 0 ist.

Thomas

  1. Hallo Thomas,

    So weit theoretisch. Denn das Passwort wird auch dann überprüft, wenn bei activ eine 0 ist.

    Die Selfpredigt vorweg:

    Du müsstest auf jeden Fall noch Fehlerprüfungen nach prepare und execute ergänzen. Beide können FALSE liefern und dann ist die Weiterverarbeitung nicht möglich.

    Du solltest nicht SELECT * verwendest. Tut man in Programmen nicht, man listet explizit die Spalten auf, die man abfragen will. Das ist für die Lesbarkeit des Programms besser.

    Zu deinem Problem: Auf der Seite zu PDOStatement::fetch steht dieser Userkommentar:

    WARNING:
    fetch() does NOT adhere to SQL-92 SQLSTATE standard when dealing with empty datasets.

    Instead of setting the errorcode class to 20 to indicate "no data found", it returns a class of 00 indicating success, and returns NULL to the caller.

    Ein anderer Kommentator widerspricht:

    A prior poster indicated that this function returns a NULL when there are no results. This is not true. This function returns an empty array.

    Beides würde in deinem Fall heißen, dass deine Abfrage auf $rows !== FALSE fehlschlägt, weil in $rows der Wert NULL oder ein leeres Array steht. Da ich immer while ($rows) programmiert habe, kann ich tatsächlich nicht sagen, was $rows enthält wenn man 4 Zeilen gelesen hat und keine fünfte mehr existiert.

    Ersetze die Prüfung $rows !== FALSE durch $rows. Die Werte FALSE, NULL und ARRAY() sind allesamt falsy, d.h. du würdest nur bei einer gefüllten Row in die Passwort-Verfizierung laufen.

    if ($row && password_verify($passwort, $user['passwort'])) {
       // authorize user
    }
    

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Tach!

      Beides würde in deinem Fall heißen, dass deine Abfrage auf $rows !== FALSE fehlschlägt, weil in $rows der Wert NULL oder ein leeres Array steht.

      Mit einfachem Debugging kann man sich darüber Gewissheit verschaffen. Sollte man immer tun, wenn Wunsch und Wirklichkeit nicht übereinstimmen. var_dump($row); klärt auf.

      dedlfix.

    2. Hallo Rolf,

      ein Nachtrag - ich habe das nun mit PHP 7.4 überprüft und kann es nicht nachvollziehen. Egal ob die Query 0 Treffer hat oder mehrere Treffer und man bis zum Ende gelesen hat - fetch liefert FALSE wenn kein Satz mehr da ist.

      Möglicherweise beziehen sich die Userkommentare auf ältere PHP Versionen. Welche PHP Version verwendest Du?

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo,

        mit PHP 7.4

        WAS? So was Altes verwendest du? Aktuell ist doch Version 8!

        scnr

        Gruß
        Kalk

        1. Hallo Tabellenkalk,

          ein bisschen Zeit hab ich ja noch.

          s

          @Christian Kruse: Wiese macht ?size=medium das Bild kaputt?

          Die Ergebnisse sind da aber gleich.

          Rolf

          --
          sumpsi - posui - obstruxi
        2. Aktuell ist doch Version 8!

          Bei mir für Debian/Raspian/Armbian

          /etc/apt/sources.list.d/php-sury.org.list:

          deb https://packages.sury.org/php/ buster main
          

          Weil PHP8 noch nicht in den Repos der Distributionen angekommen ist und das Selbst-Kompilieren womöglich nicht ganz so trivial durchführbar ist, wie es die README.txt der Quelle erscheinen lässt.