PHP MVC Sessions

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • PHP MVC Sessions

    Hallo,

    ich arbeite zur Übung mit diesem MVC Framework. https://github.com/codewithdary/MVCF...r/mvcframework

    Jetzt habe ich allerdings ein Problem mit den Sessions.
    Ich hatte zuerst eine Klasse mit den üblichen Methoden. Jedoch bekam ich da immer den Header sent fehler.

    Jetzt arbeite ich mit einer session helper funktion.

    Diese wird überall eingebunden und zu beginn die session gestartet
    <?php
    session_start();

    zwei funktionen lauten:

    function setCsrf(){
    //echo bin2hex(random_bytes(32));
    $_SESSION['_token'] = bin2hex(random_bytes(32));
    return $_SESSION['_token'];
    }

    function getCsrf(){
    return $_SESSION['_token'] ?? false;
    }

    diesen token übergebe ich bei jeder POST übermittlung. Mein Problem ist jedoch, dass die token nie übereinstimmen.

    <input type="hidden" name="_token" value="<?php echo setCsrf();?>">

    im Controller hole ich mir den token:
    $sess = getCsrf();

    && ($_POST['_token'] == $sess ))

    Warum stimmen diese tokens nie überein? Hat jemand eine Idee bzw weiß woran das liegt=?

    Vielen Dank schon mal im Voraus
    ACHTUNG (ich bin anfänger, und hoffe, dass ich mich einigermaßen verständlich ausgedrückt habe)

  • #2
    Warum stimmen diese tokens nie überein?
    Wer sagt das? Du postest nur die Hälfte des relevanten Codes, so dass man raten müsste.

    Mach mal ein var_dump() und schau, was wirklich in $_POST und $_SESSION enthalten ist. Ich könnte mir vorstellen, dass es an einer anderen Bedingung im IF liegt, immerhin ist in Deinem Code-Ausschnitt ein && zu sehen, was darauf hinweist, dass Du uns den linken Teil verheimlichst.

    und btw.
    Ich hatte zuerst eine Klasse mit den üblichen Methoden. Jedoch bekam ich da immer den Header sent fehler.
    Das sind klassische Fehler, die man beheben kann und sollte, bevor man alles umbaut.

    Kommentar


    • #3
      Hallo, erstmal danke für deine Antwort
      Ich wollte keinen Code verheimlichen. Ich habe nur versucht, dass wichtigste rauszuholen.

      Du hast mir jetzt Mut gemacht, es mit der Session Klasse nochmal in Angriff zu nehmen. Ich versuche alles unterzubringen was ich bis dato alles versucht habe.

      1. Schritt: Ich habe den Code von Github minimal umgebaut um auch den composer nutzen zu können. Der Code hat danach wie davon fehlerfrei funktioniert.

      Meine Session Klasse befindet sich im lib folder:

      <?php
      namespace app\lib;


      class Session{
      private static $instanz=NULL;

      private function __construct(){}

      public static function init(){
      if( is_null(self::$instanz) ){
      self::$instanz = new Session;
      self::sessionStart();
      }
      return self::$instanz;
      }

      private static function sessionStart(){

      /* if( empty(session_id()) && !headers_sent()){
      session_start();
      } */

      if( session_status() !== PHP_SESSION_ACTIVE ){
      session_start();
      };
      }

      public function sessionDelete(){
      $this->instanz = NULL;
      session_destroy();
      $_SESSION = [];
      }

      public function setLoginData(){
      $_SESSION['login'] = $_SERVER['REMODE_ADDR'].' '.$_SERVER['HTTP_USER_AGENT'];
      }

      public function checkLoginData(){
      return $_SESSION['login'] == $_SERVER['REMODE_ADDR'].' '.$_SERVER['HTTP_USER_AGENT'] ? true : false;
      }

      public function __set($key, $value){
      $_SESSION[$key] = $value;
      }

      public function __get($key){
      return $_SESSION[$key] ?? '';
      }

      public function setCsrf(){
      //echo bin2hex(random_bytes(32));
      $_SESSION['_token'] = bin2hex(random_bytes(32));
      return $_SESSION['_token'];
      }

      public function getCsrf(){
      return $_SESSION['_token'] ?? false;
      }

      }


      2. Schritt:

      Template:

      Code am anfang:

      <?php require_once APPROOT . '../views/layouts/header.php' ?>
      <?php require_once APPROOT . '../views/layouts/navbar.php' ?>

      <?php
      use app\lib\Session;

      ?>

      <div class="container py-5">html ...... form

      Hidden field:

      <input type="hidden" name="_token" value="<?php echo Session::init()->setCsrf();?>">
      <button type="submit" class="btn btn-dark">speichern</button>


      3. Schritt:
      Controller:

      Session KLasse wird eingebunden:
      <?php

      namespace app\controllers;

      use app\lib\Controller;
      use app\models\User;
      use app\lib\Session;
      use Gump;


      class Users extends Controller{ .... bla bla


      if(!empty($_POST)){

      $sess = Session::init()->getCsrf();
      var_dump('sess CONTROLLER: ',$sess);
      echo '<hr>';
      var_dump('POST TOKEN', $_POST['_token']);


      if ( ($_SERVER['REQUEST_METHOD']=='POST') && ($_POST['_token'] == $sess )) {


      NACH DER VALIDIERUNG:


      $_POST = [];
      $sess->sessionDelete();

      return $this->view('users/create', $data);


      Bis zur Validierung komme ich allerdings nicht, denn sofort:

      string(17) "sess CONTROLLER: " bool(false) string(10) "POST TOKEN" string(249) "
      Warning: session_start(): Cannot start session when headers already sent in ...\mvcJennyNeu\app\lib\Session.php on line 25
      9885739650a8cadb99a2a055751347b257fc6c2177f3efc4764888d7582931ed"

      Die Zeile 25 in der Session Klasse ist : session_start();

      Ich habe sehr viele Möglichkeiten bereits ausprobiert und natürlich schon alle möglichen Hilfestellungen durchgelesen. (session immer am anfang vor html) keine leerzeichen beim schließenenden PHP tag usw...

      Falls du noch weitere Codeteile benötigst, einfach schreiben
      Danke sehr

      Kommentar


      • #4
        "Cannot start session when headers already sent in ..."

        Im verheimlichten Teil (...) liegt die Erklärung, wo die Fehlerursache ist. Bzw. wenn es dort nicht steht, dann kannst du es mit headers_sent() ermitteln.
        Zuletzt geändert von h3ll; 04.05.2022, 14:58.

        Kommentar


        • #5
          welcher Teil ?

          Lg

          Kommentar


          • #6
            Irgendwo in der Fehlermeldung müsste stehen "output started at" und darauf folgt die fehlerhafte Stelle. Wenn nicht, dann wie gesagt mit headers_sent() ermitteln, wo die Ausgabe stattgefunden hat.

            Kommentar


            • #7
              Wie ermittlet man den headers_send ?
              Wie gesagt ich bin am üben und noch Anfänger.

              Ich habe die ganze fehlermeldung kopiert. Ich kann auch gerne einen Screen davon machen, aber da steht nur das was ich schon gepostet habe.

              Kommentar


              • #8
                das steht in meiner index.php (public) für FM


                <?php
                error_reporting(-1);
                ini_set('display_errors', 'On');


                require_once '../vendor/autoload.php';
                require_once '../app/require.php';


                //phpinfo();

                Kommentar


                • #9
                  PHP-Code:
                  if (!headers_sent($filename$linenum)) {
                      
                  header ('Location: http://www.example.com/');
                      exit;

                  // Wahrscheinlich wollen Sie hier eine Fehlermeldung auslösen
                  } else {

                      echo 
                  "Header bereits gesendet in $filename in Zeile $linenum\n" .
                           
                  "Redirect nicht moeglich, klicken Sie daher statt dessen <a " .
                           
                  "href=\"http://www.example.com\">diesen Link</a> an\n";
                      exit;

                  Von: https://www.php.net/manual/de/function.headers-sent.php

                  Statt dem header() Aufruf gehört halt dein session_start() rein.

                  Kommentar


                  • #10
                    und dieser teil kommt in die Session Klasse ?

                    da wo mein session_start() ist ?

                    private static function sessionStart(){

                    /* if( empty(session_id()) && !headers_sent()){
                    session_start();
                    } */

                    if( session_status() !== PHP_SESSION_ACTIVE ){
                    session_start();
                    };
                    }

                    Kommentar


                    • #11
                      Ja.

                      Kommentar


                      • #12
                        so wird mir nicht mal mehr mein speichern button angezeigt. Entferne ich das else, lande ich auf einer weißen Seite. Funktioniert also auch nicht.

                        private static function sessionStart(){


                        if( session_status() !== PHP_SESSION_ACTIVE ){
                        if (!headers_sent($filename, $linenum)) {
                        header (session_start());
                        exit;

                        // Wahrscheinlich wollen Sie hier eine Fehlermeldung auslösen
                        } else {

                        echo "Header bereits gesendet in $filename in Zeile $linenum\n" .
                        "Redirect nicht moeglich, klicken Sie daher statt dessen <a " .

                        exit;
                        }
                        }

                        Kommentar


                        • #13
                          Wie kommst du bitte auf die Idee session_start() in header() zu packen?

                          Und die exit solltest du auch entfernen, ich denke nicht, dass du das willst.

                          Kommentar


                          • #14
                            guter Punkt. Jetzt hab ich es so:

                            private static function sessionStart(){

                            /* if( empty(session_id()) && !headers_sent()){
                            session_start();
                            } */

                            if( session_status() !== PHP_SESSION_ACTIVE ){
                            if (!headers_sent($filename, $linenum)) {
                            session_start();

                            // Wahrscheinlich wollen Sie hier eine Fehlermeldung auslösen
                            } else {

                            /* echo "Header bereits gesendet in $filename in Zeile $linenum\n" .
                            "Redirect nicht moeglich, klicken Sie daher statt dessen <a " .

                            exit; */
                            }
                            }
                            }




                            Fehler:
                            Jetzt kann im Controller keine Session erstellt werden (ausgabe bool(false)

                            string(17) "sess CONTROLLER: " bool(false) string(10) "POST TOKEN" string(64) "334242ab87f821c39e844ac9c5c687108356c9bc8fda17ff25d98e0a983520c0"

                            Kommentar


                            • #15
                              das gleiche Problem hatte ich auch mit der gefundenen Lösung aus dem Netz:

                              if( empty(session_id()) && !headers_sent()){
                              session_start();

                              hier bekam ich keine Header Fehlermeldung mehr. Zum dank wurde auch auch mein token nicht erzeugt.

                              Kommentar

                              Lädt...
                              X