SQL-Abfrage = doppelte Datensätze, $_SESSION = Null auf Folgeseite

pyretta

Mitglied
Hallo,

ich bin noch PHP und MySQL Anfänger und versuche ein einfaches Login-Script zu schreiben, aber irgendwie funktioniert das nicht richtig. Es fängt schon damit an, dass die SQL-Abfrage die Werte doppelt ausgibt laut var_dump. Die Tabelle die ich anspreche hat 6 Spalten, in dem Array "$benutzer" sind aber 12 Einträge.

SQL Abfrage in der Loginseite:
PHP:
$result = mysql_query("SELECT * FROM reg_tbl_user WHERE user_name = '$benutzername' AND user_passwort = '$passwort_sha1' GROUP BY user_name") or die("Anfrage fuer 'reg_tbl_user' war nicht erfolgreich. Error: " . mysql_error());
      $benutzer = mysql_fetch_array($result);

Ich habe die mysql_query schon in phpmyadmin getestet und dort hat sie auch funktioniert, ohne die Werte doppelt auszugeben. Ich habe sogar versucht durch "GROUP BY" die Anzahl zu begrenzen, was eigentlich nicht nötig wäre, denn der Benutzername ist unique und momentan ist auch nur ein Testeintrag in der Tabelle eingetragen. Aber das brachte auch nicht den gewünschten Erfolg. Fehlermeldungen erhalte ich auch keine.

Nach einem erfolgreichen Login soll der User auf eine andere Seite weitergeleitet werden. Das versuchte ich wie folgt:

PHP:
header('Location: folgeseite.php');
ich versuchte es auch mit vollständiger URL:
Code:
header('Location: http://www.domain.de/folgeseite.php');

Hatte so nicht funktioniert, also habe ich die Krücke über JS genommen:
PHP:
echo "<script type='text/javascript'>$(document).ready(function(){window.location = 'folgeseite.php';});</script>";
Ich hab dann auch gelesen, dass "header" nur dann aufgerufen werden kann, wenn vorher keine Ausgabe erfolgt ist. Ich habe dann alle "echo" und "var_dump" Befehle entfernt, die "or die" habe ich drin gelassen, weil ich dachte dass hier keine Ausgabe stattfindet, weil keine Fehlermeldung angezeigt wurde. Hätte ich das auch entfernen sollen?

Die im Login erhaltenen Werte versuchte ich dann in einer SESSION zu speichern und an die Folgeseite zu übergeben.

In der Loginseite:
PHP:
session_start();
[...]
$_SESSION['benutzer'] = $benutzer;

Innerhalb der Loginseite kann ich mit mit
PHP:
var_dump($_SESSION['benutzer']);
das gespeicherte Array abrufen, zwar wie anfangs erwähnt mit doppelten Werten, aber immerhin. In der Folgeseite geht das leider nicht. Da gibt mir var_dump immer "NULL" aus.

Aufruf in der Folgeseite:
PHP:
session_start();
var_dump($_SESSION['benutzer']);

Was mache ich falsch?

Ich freue mich über jegliche Hilfe.
Vielen Dank schon mal im Voraus.

Grüße,
pyretta
 
ich bin noch PHP und MySQL Anfänger und versuche ein einfaches Login-Script zu schreiben
STOPP!

1. Du benutzt die alte MySQL-Erweiterung, die bald entfernt wird.
2. Neben der alten MySQL-Erweiterung hast du immer noch SQL Injection-Sicherheitslöcher.
3. Du benutzt nur SHA1 zum Hashen der Passwörter.

Bevor du irgendwann und irgendetwas weiter programmierst, empfehle ich dir ganz, ganz dringend Lektüre über die drei oben genannten Punkte zu lesen. Die Punkte 1 und 2 kannst du mit einer Umstellung auf MySQLi oder PDO lösen. Bei MySQLi bitte Prepared Statements nutzen; bei PDO gibt es sowieso keine andere Option. Bei Punkt 3 würde ich bcrypt + Salts empfehlen, siehe auch die sehr guten Antworten auf Security.SE: http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords
 
Wow! Vielen Dank für deine schnelle Antwort. Das "mysql_fetch_array" ist meines Wissens nach doch erst ab PHP 5.5 veraltet. Oder? Wir setzen momentan noch PHP 5.3.28 ein. Geht damit denn schon das "mysqli_fetch_array"? Die PHP Injections versuche mit "mysql_real_escape_string" zu vermeiden. Das scheint auch veraltet zu sein, aber ich weiß ehrlich gesagt nicht wie es sich mit "htmlspecialchars" oder "htmlentities" verhält. Wenn der Username z. B. "max_mustermann" heisst, wird das Sonderzeichen dann auch umgeschrieben? Und wird das dann auch so in die Datenbank geschrieben? Und Wie ist das mit den Passwörtern in denen ja einige Sonderzeichen enthalten sein sollten? Das mit den Salts und bcrypt sehe ich mir gleich mal an. Vielen Dank für den Link.
 
Die MySQLi-Erweiterung ist seit PHP 5.0.0 funktionsfähig!
Auch wenn es erst offiziell ab 5.5.0 als veraltet gilt, so wurde der Wechsel doch schon vorher angepriesen.
mysql_real_escape_string() hat nichts mit htmlspecialchars() (bzw. htmlentities()) zu tun. Ersteres maskiert Eingaben für das Einsetzen in SQL-Queries. Zweiteres maskiert Ausgaben für die Ausgabe in einem HTML-Kontext.
Die meisten Passwort-Hashs enthalten sowieso keine Sonderzeichen.

Bezüglich Sonderzeichen solltest du dich immer um das richtige Encoding kümmern. Stimmt dies auf beiden Seiten (z. B. bei der Kommunikation PHP <--> DB), dann werden auch keine Probleme auftreten.

mysql_real_escape_string() kann (konnte) auch umgangen werden: http://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string
 
Nochmals vielen Dank. Wieder was dazu gelernt @maskieren.

Ich habe nun alle mysql Erweiterungen in mysqli umgeschrieben. Allerdings funktionieren jetzt die Datenbankabfragen nicht mehr.

Sieht dann so aus:
PHP:
$passwort = mysqli_real_escape_string($passwort);
      $passwort_sha1 = sha1($passwort); 
      $benutzername = mysqli_real_escape_string($benutzername);
      $result = mysqli_query("SELECT * FROM reg_tbl_user WHERE user_name = '$benutzername' AND user_passwort = '$passwort_sha1' GROUP BY user_name") or die("Anfrage fuer 'reg_tbl_user' war nicht erfolgreich. Error: " . mysqli_error($link));
      $benutzer = mysqli_fetch_array($result);

Es gibt mir jetzt immer den "die" Text aus, aber ohne Fehlermeldung. Die Datenbankverbindung habe ich in einer anderen PHP-Datei die ich inkludiere. Dort wird die Variable "$link" mit den DB-Zugangsdaten gesetzt.
 
Hast du den Aufbau der Verbindung auch an MySQLi angepasst?

Und wieso maskierst du das Passwort? Das ist falsch, denn den Rückgabewert davon fütterst du an SHA1 und nicht an die DB. Deswegen maskierst du fälschlicherweise Zeichen, die nicht hätten maskiert werden dürfen.
 
Dein sowohl mysqli_real_escape_string als auch mysqli_queri erwarten den Mysqli-Link als ersten Parameter.

PHP:
$passwort = mysqli_real_escape_string($link, $passwort);
      $passwort_sha1 = sha1($passwort);
      $benutzername = mysqli_real_escape_string($link, $benutzername);
      $result = mysqli_query($link, "SELECT * FROM reg_tbl_user WHERE user_name = '$benutzername' AND user_passwort = '$passwort_sha1' GROUP BY user_name") or die("Anfrage fuer 'reg_tbl_user' war nicht erfolgreich. Error: " . mysqli_error($link));
      $benutzer = mysqli_fetch_array($result);

Das er keinen Error ausgeben hat damit zutun, dass er nicht bis zum die gekommen ist, da er beim mysqli_real_escape_string hängen geblieben ist.
An dieser Stelle hat er die Wahrscheinlich keinen Error angezeigt, da das error_reporting abgestellt sein wird.
Außerdem wenn du das Passwort verhashst musst du es nicht unbedingt escapen. ;)
 
Außerdem wenn du das Passwort verhashst musst du es nicht unbedingt escapen. ;)
Wahrscheinlich meinst du es so, aber um es deutlich zu machen: Es ist schlichtweg falsch, das Passwort zu escapen!
Den Fehler wirst du genau dann bemerken, wenn du bspw. dein DB-System änderst. Das neue maskierst vielleicht nicht mehr alle, die das alte maskiert hast. Somit musst du jetzt die Maskier-Funktion simulieren, um beim ersten Login auf dem neuen System den Nutzer anmelden zu können. (Danach hast du das PW und kannst einen neuen Hash speichern.)
 
da hab ichs wohl zu gut gemeint mit dem maskieren :D hoppala.
Ok. Auch wieder was dazu gelernt. Dass ich jedesmal den "$link" dazu packen muss war nun auch neu für mich. Vielen Dank ihr beiden!
 
Zurück