PHP MySql Login / Passwort überprüfung?
Kann mir da jemand sagen wo der Fehler liegt ? Ich bin da am verzweifeln.
Login, Registrierung, Fehlermeldung, SQL Struktur habe ich alles in die Frage gepackt damit ihr einen besseren überblick habt.
login.php:
<?php
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'TestApp';
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$username = htmlspecialchars(stripslashes(trim($_POST['username'])));
$password = htmlspecialchars(stripslashes(trim($_POST['password'])));
$statement = $pdo->prepare("SELECT * FROM user WHERE username = :username");
$result = $statement->execute(array('username' => $username
));
$user = $statement->fetch();
//Überprüfung des Passworts
if ($user !== false && password_verify($username, $password['passwort'])) {
$_SESSION['userid'] = $user['id'];
die('Login erfolgreich. Weiter zu <a href="geheim.php">internen Bereich</a>');
} else {
$errorMessage = "Nutzername oder Passwort war ungültig<br>";
}
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() ;
exit;
}
Konsole :
<br />
<b>Warning</b>: Undefined variable $pdo in <b>C:\xampp\htdocs\Test\assets\php\login.php</b> on line <b>14</b><br />
<br />
<b>Fatal error</b>: Uncaught Error: Call to a member function prepare() on null in C:\xampp\htdocs\Test\assets\php\login.php:14
Stack trace:
#0 {main}
thrown in <b>C:\xampp\htdocs\Test\assets\php\login.php</b> on line <b>14</b><br />
register.php
<?php
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'TestApp';
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// POST wird mit AJAX gesendet
$username = htmlspecialchars(stripslashes((trim($_POST["username"])))) ;
$password = password_hash(htmlspecialchars(stripslashes((trim($_POST["password"])))) ,PASSWORD_DEFAULT) ;
$cash = 100;
// Schreibt in die Datenbank
$sql = "INSERT INTO user (username,password,cash) VALUES (:username,:password,:cash) ";
$sqlvars = array("username" => $username,
"password" => $password,
"cash" => $cash);
$Abfrage = $conn->prepare($sql);
$Abfrage->execute($sqlvars);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
exit;
}
SQL STRUKTUR :
Datenbankname : Test
Tabelle : user , 5 Spalten/Rows
- id | int , (auto increment)
- username | varchar , (unique)
- password | varchar, (gehasht mit salt sha512)
- cash | varchar
- time | datetime, (mit current time stamp)
und ich mache alles mit AJAX.
-PDO statt mysqli
3 Antworten
In Zeile 14 von login.php verwendest du die nicht definiert Variable $pdo statt $conn, also:
$statement = $conn->prepare("SELECT …
Die Fehlermeldung ist übrigens absolut aussagekräftig und du solltest versuchen, diese zu lesen und zu verstehen.
In Zeile 19 machst du aus einem String auf einmal ein Array:
$password['passwort']
Da sollte nur $password stehen. Allerdings solltest du dir noch mal die Dokumentation von password_verify ansehen:
https://www.php.net/manual/de/function.password-verify.php
Du vergleichst den Nutzernamen mit dem Passwort, was natürlich nicht funktionieren kann. Stattdessen musst du das eingegebene Passwort mit dem Passwort-Hash aus der Datenbank vergleichen. Dazu holst du dir den Hash vorher aus der Datenbank und testest ihn dann mit password_verify gegen das eingegeben Passwort.
Mir ist das klar, aber deine Schreibe fand ich missverständlich:
Du vergleichst den Nutzernamen mit dem Passwort, was natürlich nicht funktionieren kann. Stattdessen musst du das eingegebene Passwort mit dem Passwort-Hash aus der Datenbank vergleichen.
Es sind sowohl Nutzername als auch Passwort abzugleichen, nicht „stattdessen“. Ich bin halt Programmierer und muss meinem Rechenknecht exakte Anweisungen geben.
Du hast meinen letzte Satz vergessen zu zitieren, der genau erklärt, wie es gemacht wird:
Dazu holst du dir den Hash vorher aus der Datenbank und testest ihn dann mit password_verify gegen das eingegeben Passwort.
Einfach zu schreiben, dass man Nutzername und Passwort abgleichen muss, wäre nämlich auch missverständlich, weil man das eben üblicherweise nicht gleichzeitig macht. Erst holt man sich den Datensatz mit dem Nutzer über den Nutzernname und dann vergleicht man, ob der Passwort-Hash im Datensatz mit vom dem eingegeben Passwort übereinstimmt.
In einer Datenbankabfrage lässt sich das normalerweise nicht erledigen, da Passwörter immer mit einem zufälligen Salt versehen sein sollten.
Die Variable heißt doch $conn statt $pdo, wenn ich das richtig sehe.
Ok nächste Fehlermeldung mit der ich nichts anfangen kann xD
<br />
<b>Fatal error</b>: Uncaught TypeError: Cannot access offset of type string on string in C:\xampp\htdocs\Test\assets\php\login.php:19
Stack trace:
#0 {main}
thrown in <b>C:\xampp\htdocs\Test\assets\php\login.php</b> on line <b>19</b><br />
Lernst du erst programmieren? Dann mach bitte zuerst etwas anderes. Eine Sprache mit strikter Typisierung und Typprüfung zur Compilierzeit (C, VB, Java).
Zum Problem: Welches ist Zeile 19? Die mit
$password['passwort']
Was soll der Ausdruck bewirken?
Lernst du erst programmieren? Dann mach bitte zuerst etwas anderes. Eine Sprache mit strikter Typisierung und Typprüfung zur Compilierzeit (C, VB, Java).
Also JavaScript mache ich schon etwas länger aber noch lange kein Profi,
php ist mir aber echt ein rätsel und die Fehlermeldungen nicht so leicht
$password['passwort']
Was soll der Ausdruck bewirken?
Garnicht, Das ist schon peinlich xD
Danke hab es verbessert
//Überprüfung des Passworts
if ($user !== false && password_verify($username, $password)) {
$_SESSION['userid'] = $user['id'];
die('Login erfolgreich. Weiter zu <a href="geheim.php">internen Bereich</a>');
} else {
$errorMessage = "Nutzername oder Passwort war ungültig<br>";
echo $errorMessage;
}
Leider lande ich auch hier im Else teil
mit Nutzername oder Passwort war falsch
Obwohl es genau so in der Datenbank steht,
Hast du vielleicht noch ein paar fehler von mir entdecken können ?
Sollte wohl einfach nur $password sein. Er hat das wohl imt dem schlüsselbasierten Zugriff bei $_POST verwechselt.
Mein Tipp wäre ja schlafen zu gehen udn it frischem Kopf weiter zu machen :-D.
Du mußt das übermittelte Passwort gegen das Passworthash aus der Datenbank prüfen.
$user ist doch das gesamte Tupel.
Für php habe ich mich halt entschieden um schnell ein cooles Backend hinzubekommen,
Verglichen mit Java oder C ist das ja noch wenig aufwand auch wenn es seltsam ist.
Fokusiere mich eher auf Frontent
Prüfe den Wert von "$user". Wenn das true ist, liegt's am Rückgabewert der Funktion password_verify. Da ich nicht weiß, was in der Funktion passiert, kann ich das schlecht beurteilen.
Statt "$user !==false" kannst du einfach "$user == true" schreiben oder einfach nur "$user". Bei letzterem bin ich mir nicht sicher, denn ich leider keine PHP.
EDIT: Hab mich in der Variable vergriffen. $result, nicht $user.
//Überprüfung des Passworts
if ($user !== false && password_verify($password, $user['password'])) {
$_SESSION['userid'] = $user['id'];
die('Login erfolgreich. Weiter zu <a href="geheim.php">internen Bereich</a>');
} else {
$errorMessage = "Nutzername oder Passwort war ungültig<br>";
echo $errorMessage;
hab es doch noch hinbekommen, das hat funktioniert
Gute nacht und danke für die hilfe 😂
Mit === true aber irgendwie nichtmehr, obwohl es eigentlich dasselbe heisst
Ja heisst sie, glaube der fehler liegt hier
$statement = $pdo->prepare("SELECT * FROM user WHERE username = :username");
müsste
$statement = $conn->prepare("SELECT * FROM user WHERE username = :username");
sein
Um den Fehler zu beheben, müssen Sie die Variable $pdo in Zeile 14 durch $conn ersetzen. Der korrigierte Code sollte wie folgt aussehen:
<?php
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'TestApp';
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$username = htmlspecialchars(stripslashes(trim($_POST['username'])));
$password = htmlspecialchars(stripslashes(trim($_POST['password'])));
$statement = $conn->prepare("SELECT * FROM user WHERE username = :username");
$result = $statement->execute(array('username' => $username
));
$user = $statement->fetch();
//Überprüfung des Passworts
if ($user !== false && password_verify($username, $password['passwort'])) {
$_SESSION['userid'] = $user['id'];
die('Login erfolgreich. Weiter zu <a href="geheim.php">internen Bereich</a>');
} else {
$errorMessage = "Nutzername oder Passwort war ungültig<br>";
}
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() ;
exit;
}
?>
Wenn das Passwort einzigartig UNIQUE ist, üblicherweise wird das bei der Neuanlage/Änderung des Kontos nicht überprüft.