EneR: Session

Guten Morgen,
Ich hab folgenden script:
<?php
 include ("auth.php"); /* auth.php nach selfhtml.org */
 include ("sqlLogin4.php"); /* einloggen in die sql- datenbank 4*/

$username = $_SESSION['username'];
 $server = $_SESSION['server'];
        /*eigentliches Programm*/
?>
Wenn ich mich jetzt einlogge funktioniert das einwandfrei (bzw funktioniert nicht bei falschem Passwort) aber oben drüber teht immer:

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /var/www/web277/html/GAME/game.php:1) in /var/www/web277/html/GAME/auth.php on line 2

auth.php:
<?php
     session_start();

$hostname = $_SERVER['HTTP_HOST'];
     $path = dirname($_SERVER['PHP_SELF']);

if (!isset($_SESSION['angemeldet']) || !$_SESSION['angemeldet']) {
      header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/login.php');
      exit;
      }
?>

login.php:
<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  session_start();

$username = $_POST['username'];
  $passwort = $_POST['passwort'];
  $server = $_POST['s'];
  include ("sqlLogin4.php");

$abfrage = "SELECT password FROM usrdata WHERE Usrname LIKE '$username'";
  $ergebnis = mysql_query($abfrage);
  if($row = mysql_fetch_object($ergebnis)) {
      $passwort_sql = $row->password;
  }

$hostname = $_SERVER['HTTP_HOST'];
  $path = dirname($_SERVER['PHP_SELF']);

// Benutzername und Passwort werden überprüft
  if ($username == $username && $passwort == $passwort_sql) {
   $_SESSION['angemeldet'] = true;

// Weiterleitung zur geschützten Startseite
   if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {
    if (php_sapi_name() == 'cgi') {
     header('Status: 303 See Other');
      $_SESSION['username'] = $username;
      $_SESSION['server'] = $server;
    }
    else {
     header('HTTP/1.1 303 See Other');
     $_SESSION['username'] = $username;
     $_SESSION['server'] = $server;
    }
   }

header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/game.php');
  $_SESSION['username'] = $username;
  $_SESSION['server'] = $server;
  exit;
  }
 }

header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/index.php');
?>

  1. Hallo,

    <?php
    include ("auth.php"); /* auth.php nach selfhtml.org */
    [...]
    ?>
    Wenn ich mich jetzt einlogge funktioniert das einwandfrei (bzw funktioniert nicht bei falschem Passwort) aber oben drüber teht immer:

    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at /var/www/web277/html/GAME/game.php:1) in /var/www/web277/html/GAME/auth.php on line 2

    dann hat die Ausgabe an den Client (Browser) schon begonnen, bevor session_start() aufgerufen wurde. Und die Fehlermeldung sagt sogar, wo: In Zeile 1 von game.php (also ganz am Anfang).

    Merke: Alle PHP-Anweisungen, die in irgendeiner Weise HTTP-Header senden oder beeinflussen, müssen ausgeführt werden, bevor irgendein Stück Klartext ausgegeben wird. Sogar ein Zeilenumbruch oder ein Leerzeichen genügt schon, um den Fehler auszulösen. Der Start-Tag des PHP-Abschnitts (also das "<?php") muss daher ganz am Anfang der Datei stehen!
    Das betrifft vor allem die Funktionen session_start(), setcookie() und header().

    So long,
     Martin

    --
    Der Alptraum jedes Computers:
    "Mir war, als hätte ich gerade eine 2 gesehen."
  2. Hallo..
    Ich hoffe mal sehr, dass du dein Login Script nochmal überdenkst. Als erstes kannst du sowas hier nicht machen:

    $username = $_POST['username'];
      $passwort = $_POST['passwort'];
      $server = $_POST['s'];

    Du unterziehst die Userdaten keiner Kontrolle. Ein User könnte dir hier alles Mögliche unterjubeln.

    Das kann so nicht bleiben, wenn du die Usereingaben nicht überprüfst (mysql_real_escape_string)

    $abfrage = "SELECT password FROM usrdata WHERE Usrname LIKE '$username'";
      $ergebnis = mysql_query($abfrage);

    Hier hast du eine IF Bedingung. Was würde denn passieren, wenn das Ergebnis NULL ist, also wenn es kein Passwort gibt, weil der Username den man eingeben hat, nicht existiert?
    Ganz einfach: Diese Bedingung wäre FALSE, also wird der Code in der Bedingung nicht ausgeführt.

    if($row = mysql_fetch_object($ergebnis)) {
          $passwort_sql = $row->password;
      }

    Da das Ergebnis der Bedingung ja NULL war ist die Variable $passwort_sql also leer. Bei der Anmeldung gibt jetzt der böse User auch kein Passwort ein. Damit wäre die Bedingung "$passwort == $passwort_sql" schonmal erfüllt. Und die Bedingung "$username == $username" ist sowieso IMMER TRUE.

    // Benutzername und Passwort werden überprüft
      if ($username == $username && $passwort == $passwort_sql) {
       $_SESSION['angemeldet'] = true;

    Auf den Rest gehe ich mal nicht weiter ein.

    Was heisst das jetzt alles im Klartext?
    Ich könnte mich bei deinem Script mit jedem Benutzernamen einloggen. Egal, ob er existiert oder nicht. Du speicherst den Benutzernamen danach in einer Sessionvariable ab. Wenn du anhand derer auch Benutzerrechte verteilst, hätte ich Adminrechte, wenn ich mich mit dem Benutzernamen des Admins anmelde und bei der Anmeldung das Passwortfeld leer lasse.

    Überprüfe jede Eingabe, die ein User machen kann. Stelle sicher, dass dir niemand irgendwelche Werte in Variablen unterjubeln kann, die du da nicht haben willst.

    Gruß

    1. echo $begrüßung;

      Ich hoffe mal sehr, dass du dein Login Script nochmal überdenkst. Als erstes kannst du sowas hier nicht machen:

      $username = $_POST['username'];
        $passwort = $_POST['passwort'];
        $server = $_POST['s'];
      Du unterziehst die Userdaten keiner Kontrolle. Ein User könnte dir hier alles Mögliche unterjubeln.

      Ich vermute stark, EneR und andere Anfänger können sich nicht vorstellen, was unter "alles Mögliche unterjubeln" zu verstehen ist.

      Das kann so nicht bleiben, wenn du die Usereingaben nicht überprüfst (mysql_real_escape_string)

      $abfrage = "SELECT password FROM usrdata WHERE Usrname LIKE '$username'";

      Um dem Verständnis ein wenig auf die Sprünge zu verhelfen, wäre ein kleines Beispiel recht nützlich, z.B. die Eingabe eines Benutzernamens mit einem ' drin. Anschließend vielleicht noch eins, bei dem ein Statement manipuliert wird. Das zeigt, dass das nicht nur ein sicherheitsrelevantes Problem ist, sondern auch in harmlosen Fällen zu Fehlern führt.

      $ergebnis = mysql_query($abfrage);

      Hier wäre ein Hinweis angebracht, dass mysql_query() im Fehlerfall false zurückliefert. Und dass dieser Zustand nicht berücksichtigt wird, was bei nachfolgenden mysql_*-Funktionen zu Folgefehlern führen kann, weil die eine Ressourcenkennung erwarten und kein false.

      Hier hast du eine IF Bedingung. Was würde denn passieren, wenn das Ergebnis NULL ist, also wenn es kein Passwort gibt, weil der Username den man eingeben hat, nicht existiert?
      Ganz einfach: Diese Bedingung wäre FALSE, also wird der Code in der Bedingung nicht ausgeführt.

      if($row = mysql_fetch_object($ergebnis)) {
            $passwort_sql = $row->password;

      Du versuchst auf ein Problem hinzuweisen, bei dem eine nicht in jedem Fall initialisierte Variable entstehen kann, was sich zu einem weiteren Problem entwickeln kann. Doch du beschreibst es etwas verwirrend. mysql_fetch_object() liefert entweder ein Objekt oder false, wenn keine (weiteren) Datensätze mehr verfügbar sind. Es ist zunächst nicht das Problem, dass es kein Passwort gibt, sondern dass die Abfrage eine leere Ergebnismenge geliefert hat. Infolge dessen wird der Ausdruck nicht wahr, und die Variable $passwort_sql wird nicht gesetzt.

      Wo entsteht deiner Meinung nach das NULL?

      Was heisst das jetzt alles im Klartext?
      Ich könnte mich bei deinem Script mit jedem Benutzernamen einloggen. Egal, ob er existiert oder nicht.

      Nein, denn wenn er existiert, gibt es einen Datensatz, die "if $row=..."-Bedingung greift, und die Passwortabfrage findet mit dem in der DB eingetragenen Wert statt.

      Überprüfe jede Eingabe, die ein User machen kann. Stelle sicher, dass dir niemand irgendwelche Werte in Variablen unterjubeln kann, die du da nicht haben willst.

      Das kann man als Lehrsätze so stehen lassen, aber wenn jemand nicht weiß, wie er sie zu verstehen und umzusetzen hat, nützen sie nicht all zu viel.

      echo "$verabschiedung $name";