Login-System mit Datenbank funktioniert lokal, aber nicht Online

  • PHP

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Visual_Prog.

    Login-System mit Datenbank funktioniert lokal, aber nicht Online

    Moinsen,

    ich habe eine PHP Datei, die für ein Login die Anmeldedaten aus einer Datenbank über PDO vergleicht und abruft.
    Beim erfolgreichen Login erfolgt die Weiterleitung zu einer anderen PHP.

    Das Ganze funktioniert unterm localhost, jedoch nicht wenn ich das auf meinem Webserver Online bringen möchte. Es wird dann einfach die erste PHP neugeladen, nachdem die Anmeldedaten eingegeben wurden, statt weiterzuleiten. Komischerweise funktioniert die Registrierung ohne Probleme, denn es werden die registrierten Anmeldedaten in der Datenbank aufgezeigt.
    Bevor ich hier so viel Code poste, erkundige ich mich ob es da vielleicht allgemeine Stolperfallen gibt?

    danke LG
    Der Code der Weiterleitung kann doch nicht besonders groß sein, oder etwa doch? Denn der Code würde hier schon helfen. Ohne Code kann ich nur raten und werfe den "Pfad" in den Raum, der auf dem Server evtl. anders "formuliert" sein muss.
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum
    Ja das mit dem Pfad war auch schon eine meine Vermutungen. Nur habe ich da keine Ahnung wo ich das angeben soll^^

    das hier ist die mysql.php die ich da habe:

    PHP-Quellcode

    1. <?php
    2. $host = '';
    3. $name = '';
    4. $user = '';
    5. $passwort = '';
    6. try {
    7. $mysql = new PDO("mysql:host=$host; dbname=$name;", $user, $passwort);
    8. } catch (PDOException $e) {
    9. echo "Fehler!:" . $e->getMessage() . "<br/>";
    10. die();
    11. }
    12. ?>

    Natürlich habe ich die Variablen hier nicht angezeigt, die ich vom Webserver bekommen habe.

    Bei einer anderen Datei Namens login.php wird der Fehler auf die Zeile verwiesen, wo der SELECT Befehl liegt:

    PHP-Quellcode

    1. if(isset($_POST["submit"])){
    2. require("mysql.php");
    3. $stmt = $mysql->prepare("SELECT * FROM accounts WHERE USERNAME = :user"); //username überprüfen HIER IST DER FEHLER
    4. $stmt->bindParam(":user", $_POST["username"]);
    5. $stmt->execute();
    6. $count = $stmt->rowCount();


    vielleicht hilft das ein wenig weiter bei der Problemerörterung^^
    Ähm ... und wo ist jetzt die Weiterleitung? Ich dachte, die ist das Problem. Dein Code zeigt in keiner Weise irgendwelche Weiterleitungen.

    Ich befürchte, du musst dein Problem nochmal genauer erläutern, zumindest ich verstehe im Moment nicht, wo es hakt.
    Besucht auch mein anderes Forum:
    Das Amateurfilm-Forum
    Hi,

    @Visual_Prog wo und wie wird die Weiterleitung denn gemacht? Über JavaScript? Oder header? Oder reden wir vom action Attribut der Form beim Submit?
    Ein Dump von $_POST wäre ganz nice, um mal zu sehen was da drin ist und mit welchen Werten PDO dann arbeitet. Du kannst es btw auch alternativ mal über bindValue() versuchen.

    Paar andere Sachen die mir aufgefallen und eine kurze Erwähnung wert sind:

    - Dateien sollten eigl kaum noch über require oder include eingebunden werden, sowas macht idR ein Autoloader (php-fig.org/psr/psr-4/)

    - Tabellen- und Feldnamen in SQL-Statements gehören in Backticks ("SELECT * FROM `accounts` WHERE `username` = :user")

    - Ich empfehle, beim instanziieren eines PDO objects im DSN den charset anzugeben - heutzutage wird das üblicherweise utf8mb4 sein, deine Datenbanken/Tabellen/Felder werden aller Wahrscheinlichkeit nach auch auf utf8mb4_unicode_ci o.ä. eingestellt sein.

    - Eine Variable für $mysql ist eine eher ungeile Idee, denn wenn du im nicht-globalen-scope Datenbankoperationen ausführen willst, musst du mit dem global Schlüsselwort arbeiten, und das ranzt. Lass das besser über ein Singleton object laufen für das du dann auch eine wrapper-function anlegen kannst um auf solche zentralen Mechanismen von überall aus Zugriff zu haben. Wenn du multiple Connections fahren willst oder planst, sowas in Zukunft zu machen, lässt sich die Funktionalität dafür dann auch entsprechend einfach ausbauen.

    - Datenbank credentials sind in Konfigurations- oder DotEnv Dateien besser aufgehoben, noch besser außerhalb vom document root, aber das nur als Tipp.

    - Der Try-Catch nützt dir nur was, wenn PDO für PDO::ATTR_ERRMODE auch den Wert PDO::ERRMODE_EXCEPTION zugewiesen bekommen hat, entweder via setAttribute() oder über das $options array im construct. Wenn du PHP 8 verwendest, ist das wurscht, das ist das eh standardmäßig so eingestellt, aber für alle PHP Versionen darunter sind Fehler erst mal alle auf silent gestellt.


    Zurück zum redirect:

    Läuft dein lokaler Webserver über so einen shit wie xampp oder ähnliches? Und dann wär noch interessant, ob sich das OS unterscheidet zwischen lokaler Umgebung und Online Webserver (die idR Linux benutzen). Vielleicht ist da schon was mit dem DIRECTORY_SEPARATOR verhunzt, Windows benutzt \ für Dateisystemstrukturen, Linux hingegen /. Generell an der Stelle empfehl ich dir auch, schließende ?> PHP Tags immer wegzulassen. Achte auch drauf, dass du keine wilden Whitespaces am Anfang von Dateien hast, und schau auch dass sich da nicht so ein ekliger BOM eingeschlichen hat. Denn wenn du für den redirect mit headern arbeitest in der Art wie header("Location: /some-file.php"); wird das nur funktionieren, wenn vor diesem Aufruf keine Ausgabe im Skript gemacht wurde.
    Irgendwo wirst du ja deinen single-point-of-entry haben, höchstwahrscheinlich wird die index.php das sein, dort drin würde ich auch gleich mal error_reporting auf E_ALL und display_errors via ini_set auf true setzen, damit dir keine Fehlermeldungen entgehen.
    Du siehst, zu deinem Problem mit dem redirect musst du genauere Infos liefern, hilf uns dir zu helfen ;)


    Link :thumbup:
    Hello World

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Link“ ()

    hey,
    also ich poste nochmal den Code mit der Weiterleitung.

    danke schon mal für die ausführlichen und kompetenten Antworten. Ich werde Morgen auch einmal beim Webserver anrufen, ob ich da noch was rausfinden kann. Ich meine dort funktioniert das ganze mit Linux, bei mir unterm localhost mit windows 7 und xampp.



    PHP-Quellcode

    1. <body>
    2. <?php
    3. if(isset($_POST["submit"])){
    4. require("mysql.php");
    5. $stmt = $mysql->prepare("SELECT * FROM accounts WHERE USERNAME = :user"); //username überprüfen
    6. $stmt->bindParam(":user", $_POST["username"]);
    7. $stmt->execute();
    8. $count = $stmt->rowCount();
    9. if($count == 1){
    10. //username ist frei
    11. $row = $stmt->fetch();
    12. if(password_verify($_POST["pw"], $row["PASSWORD"])){
    13. session_start();
    14. $_SESSION["username"] = $row["USERNAME"];
    15. header("Location: neueseite.php");
    16. } else {
    17. echo "Der Login ist fehlgeschlagen";
    18. }
    19. } else {
    20. echo "Der Login ist fehlgeschlagen";
    21. }
    22. }
    23. ?>
    24. <h1>Anmelden</h1>
    25. <form action="login.php" method="post">
    26. <input type="text" name="username" placeholder="Username" required> <br>
    27. <input type="password" name="pw" placeholder="Passswort" required> <br>
    28. <button type="submit" name="submit">Einloggen</button>
    29. </form>
    30. <br>
    31. <a href="register.php">Noch keinen Account?</a>
    32. </body>
    Mich wundert es, das der Code überhaupt irgendwo funktioniert. Wie @Link schon geschrieben hat, funktioniert header(...) nur, wenn vorher keine Ausgabe passiert, aber in deinem Code sind mehrere Ausgaben davor.
    @Visual_Prog also wie gesagt, du hast dort Fehler, eine header() Anweisung kann nicht funktionieren wenn davor Ausgaben im Skript gemacht wurden. Ganz oben ist in deinem Skript ja erst mal HTML und ein paar Whitespaces, also Tabs und Leerzeilen. Und dadurch wird eine header() Anweisung fehlschlagen.

    PHP-Quellcode

    1. <?php
    2. ini_set('display_errors', '1');
    3. error_reporting(E_ALL);


    Das hier muss an den Anfang deiner Datei, sonst siehst du die Fehlermeldungen sowieso nicht. Alternativ kannst du ins error log schauen, das findest du meist in /var/log/apache2/error.log oder unter httpd statt apache2.

    Dein session_start() ist an dieser Stelle im Skript komplett nutzlos, denn die Session wird immer nur dann gestartet, wenn im Skript alle Bedingungen so zutreffen dass du am Ende in Zeile 22 landest. Und nur nach session_start() kannst du auf Session Daten zugreifen. Das heißt dein session_start() muss da raus, das kommt irgendwo an eine zentrale Stelle im Skript und das am besten weit oben am Anfang, also nach den ini_set(display_errors)... Anweisungen.

    Du solltest deinen Code mal strukturieren, Einstiegspunkt ist in aller Regel die index.php im document root, also am obersten Punkt im Hauptverzeichnis deines Projekts. Von dort kannst du sowas wie eine load.php einbinden, die grundsätzliche Initialvorgänge erledigt, wie zum Beispiel das Starten der Session, das aktivieren der Fehlerausgabe und zum Definieren einiger Core Funktionen die du womöglich geschrieben hast.

    Beispiel:

    index.php

    PHP-Quellcode

    1. <?php
    2. # Enable debugging
    3. ini_set('display_errors', '1');
    4. error_reporting(E_ALL);
    5. require_once __DIR__ . '/load.php';
    6. # Was auch immer dann hier kommt, Seiten werden geladen etc...


    load.php

    PHP-Quellcode

    1. <?php
    2. # Session starten, das muss nur einmal passieren
    3. session_start();
    4. /* #### Some helper functions #### */
    5. /**
    6. * Database connection
    7. *
    8. * @return \PDO|void|null
    9. */
    10. function db() {
    11. static $pdo = null;
    12. if ($pdo === null) {
    13. try {
    14. $options = [
    15. # Fehlermodus auf Exception schalten
    16. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    17. # Native Typen bei Abfragen erhalten
    18. PDO::ATTR_STRINGIFY_FETCHES => false,
    19. # Felder assoziativ fetchen (Zugriff auf Attribute über $zeile['feldname'] statt über numerischen Feldindex)
    20. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    21. ];
    22. $pdo = new PDO("mysql:host=localhost;dbname=my_db;charset=utf8mb4", 'db_user', 'db_password', $options);
    23. # Wenn du PHP Version unter 5.3.6 nutzt, aktiviere folgende Zeile:
    24. // $pdo->exec("SET NAMES 'utf8mb4';");
    25. } catch (\Exception $e) {
    26. exit("Datenbankverbindung fehlgeschlagen: " . $e->getMessage());
    27. }
    28. }
    29. return $pdo;
    30. }
    31. /**
    32. * Dump values
    33. *
    34. * @param ...$data
    35. *
    36. * @return void
    37. */
    38. function dump(...$data) {
    39. foreach ($data as $d) {
    40. if (is_cli()) {
    41. echo "\n\n-- " . gettype($d) . " (~" . ($d ? 'true' : 'false') . ") --\n" . print_r($d, true) . "\n\n";
    42. } else {
    43. echo "<div class='dump' style='margin: 4px;padding:4px;background-color:#f4f4f4;font-family:\"courier new\",consolas,sans-serif;'><strong>" . gettype($d) . " (~" . ($d ? 'true' : 'false') . ")</strong><pre style='padding:4px;margin:4px 0;background-color:#ffffff;'>" . htmlentities(print_r($d, true), ENT_QUOTES, 'UTF-8') . "</pre></div>";
    44. }
    45. }
    46. }
    47. /**
    48. * Simple path function
    49. *
    50. * @param string $to directory or file inside your project
    51. *
    52. * @return string
    53. */
    54. function path($to = '') {
    55. $to = trim(str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $to), DIRECTORY_SEPARATOR);
    56. return __DIR__ . ($to === '' ? '' : DIRECTORY_SEPARATOR . $to);
    57. }
    58. /**
    59. * Check if interface is CLI
    60. *
    61. * @return bool|null
    62. */
    63. function is_cli() {
    64. static $climode = null;
    65. if ($climode === null) {
    66. $climode = (defined("STDIN") || array_key_exists("SHELL", $_ENV) || (defined("PHP_SAPI") && strtolower(PHP_SAPI) == "cli") || (function_exists("php_sapi_name") && strtolower((string)php_sapi_name()) == "cli"));
    67. }
    68. return $climode;
    69. }
    70. # Jetzt kannst du überall via db() die Datenbankoperationen nutzen, Beispiel:
    71. dump(db()->query("SHOW TABLES;")->fetchAll());
    72. /* ... hier ggf. weiterer Code ... */


    Zum Redirect: wenn du an der Stelle weiterleiten willst, kannst du das über header nicht mehr machen. Entweder du verzichtest auf jegliche Ausgaben vor diesem Aufruf, oder du nutzt an der Stelle dann JavaScript dafür, z.B. window.location.href = '/andere-seite.php';



    Link :thumbup:
    Hello World

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Link“ ()

    okey, ja also ich muss sagen meine PHP Kenntnisse sind noch relativ bescheiden und da muss man ja schon eine Menge beachten, wenn man das mit einer Datenbank handhaben möchte.Aber das ist schon mal Klasse dass man einen Wegweiser hat, wie es richtig geht, vielen Dank dafür!Ich habe mich jetzt entschieden das Redirect über Javascript zu machen. danke und schönes weekend!