Fabian Transchel: serialize() und multidimensionale Arrays

Hallo Forum,

ich habe folgendes Problem (das heißt ich weiß nicht, ob es eines ist - ich komme bloß nicht weiter, da das PHP-Manual recht unergiebig ist bzw. hier anscheinend ein undokumentierter Sonderfall vorliegt)

Also, ich möchte ein mehrdimensionales Array serialisieren - geht das nicht? Bzw, wenn es nicht geht, kann man sirialize schachteln?

Hier der Code, zur Erklärung: Ich hole mir CSV aus einem File und möchte die in ein multi-dimensionales Array packen, das klappt auch. Wenn ich jetzt aber das md-Array serialisiere bekomme ich nur "N;N;" zurück statt einem ordentlichen String.
<schnipp>

<?php
// Konvertieren der alten Gästebucheinträge
$daten = file("homepage/guestbook.gb");
$i = 0;
while($i < count($daten))
{
$werte = explode("|",$daten[$i]);
$guestook[$i]['name'] = $werte[0];
$guestook[$i]['datum'] = $werte[1];
$guestook[$i]['mail'] = $werte[2];
$guestook[$i]['url'] = $werte[3];
$guestook[$i]['text'] = $werte[4];
if($werte[5])$guestook[$i]['text'] = $werte[5];
$i++;
}
echo("<pre>");
print_r($guestook);
// Hier wird alles korrekt ausgegeben...
echo("</pre>");

$str = serialize($guestbook[0]['name']);
echo $str; // Gibt lediglich "N;N;" zurück.

//$fp = fopen("guestbook.gb",'a');
//fputs($fp,$gueststring,strlen($gueststring));
//fclose($fp);
?>

<schnapp>

Fabian

  1. Hallo nochmal...
    Ich hab grade bemerkt, dass im Script zig Schreibfehler waren, jetzt geht es... *schäm*

    Nix für ungut, Fabian

  2. Hallo Fabian,

    Also, ich möchte ein mehrdimensionales Array serialisieren - geht das nicht?

    Doch, natürlich geht das. Jedes mal, wenn Du ein multidimensionales Array in der Session ablegst, wird das serialisiert und wieder deserialisiert.

    $str = serialize($guestbook[0]['name']);

    serialize verwandelt den Wert null in N; => daher passiert folgendes:

    echo $str; // Gibt lediglich "N;N;" zurück.

    wenn Du 2x die serialisierte Variante von null ausgibst.

    Du solltest vielleicht mal $guestbook[0]['name'] durch var_dump jagen, am besten gleich ganz $guestbook. Was ich auch nicht verstehe, ist warum Du nicht das ganze Gästebuch serialisierst, sondern nur den Namen des ersten Eintrages.

    Grüße,

    Christian

    --
    Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
    1. Hi Christian

      Doch, natürlich geht das. Jedes mal, wenn Du ein multidimensionales Array in der Session ablegst, wird das serialisiert und wieder deserialisiert.

      Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.

      Du solltest vielleicht mal $guestbook[0]['name'] durch var_dump jagen, am besten gleich ganz $guestbook. Was ich auch nicht verstehe, ist warum Du nicht das ganze Gästebuch serialisierst, sondern nur den Namen des ersten Eintrages.

      Siehe anderes Posting, war eine Unaufmerksamkeit, ich hatte überall $guestook statt $guestbook geschrieben - das geht dann latürnicht nicht. Natürlich serailisiere ich das ganze Gästebuch, wenn es läuft...
      Wenn das geht, dann kann man theoretisch ja ein ganzes Forum mit zwei Dateien programmieren - einer forum.php und der passenden forum.txt *großeaugenkrieg*

      Vorweihnachtliche Grüße, Fabian

      1. Hallo Fabian,

        Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.

        Erneuter Einspruch, euer Ehren, ich habe nur behauptet, dass ein mehrdimensionales Array serialisiert wird, wenn Du dieses entsprechend aus der Session-Datei 'ausschneidest', dann kannst Du das wirklich durch unserialize jagen. ;-P

        Siehe anderes Posting, war eine Unaufmerksamkeit, ich hatte überall $guestook statt $guestbook geschrieben - das geht dann latürnicht nicht.

        Tja, womit bewiesen wäre, dass Du error_reporting _höchstens_ auf E_ALL ~ E_NOTICE gestellt hast, denn sonst hättest Du einen Hinweis bekommen, dass die Variable $guestbook in der Serialize-Zeile nicht existiert. ;-P

        Wenn das geht, dann kann man theoretisch ja ein ganzes Forum mit zwei Dateien programmieren - einer forum.php und der passenden forum.txt *großeaugenkrieg*

        Naja, Du solltest Dir vorher mal ein paar Gedanken zum Thema Performance von dem ganzen machen - wenn in dem Forum auch nur ein zwanzigstel von dem los ist wie hier, dann kannst Du die Methode vergessen - IMHO brauchst Du für jeden Thread eine eigene Datei. (so wie dieses Forum hier)

        Vorweihnachtliche Grüße,

        Christian

        --
        Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
        1. Hi

          Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.
          Erneuter Einspruch, euer Ehren, ich habe nur behauptet, dass ein mehrdimensionales Array serialisiert wird, wenn Du dieses entsprechend aus der Session-Datei 'ausschneidest', dann kannst Du das wirklich durch unserialize jagen. ;-P

          Ja, aber wie willst das das denn ausschneiden, wenn du nicht weißt, welcher Teil "fehlt"?

          Siehe anderes Posting, war eine Unaufmerksamkeit, ich hatte überall $guestook statt $guestbook geschrieben - das geht dann latürnicht nicht.
          Tja, womit bewiesen wäre, dass Du error_reporting _höchstens_ auf E_ALL ~ E_NOTICE gestellt hast, denn sonst hättest Du einen Hinweis bekommen, dass die Variable $guestbook in der Serialize-Zeile nicht existiert. ;-P

          Doch, sie existiert, bloß waren nur die guestbook[$i]['name']-Felder belegt, die anderen waren Dank Schusseligkeit in $guestook[...] ;-)

          Wenn das geht, dann kann man theoretisch ja ein ganzes Forum mit zwei Dateien programmieren - einer forum.php und der passenden forum.txt *großeaugenkrieg*

          Naja, Du solltest Dir vorher mal ein paar Gedanken zum Thema Performance von dem ganzen machen - wenn in dem Forum auch nur ein zwanzigstel von dem los ist wie hier, dann kannst Du die Methode vergessen - IMHO brauchst Du für jeden Thread eine eigene Datei. (so wie dieses Forum hier)

          Nein, so viel Traffic habe ich lange nicht, veilleicht zehn(!) Aufrufe (des Forums) am Tag... da macht das wohl keine Probleme...

          Fabian

          1. Hallo Fabian,

            Ja, aber wie willst das das denn ausschneiden, wenn du nicht weißt, welcher Teil "fehlt"?

            Trial & Error? *scnr* ;-)
            Ich wollte damit nur sagen, dass es _möglich_ ist. Ob es _sinnvoll_ oder _durchführbar_ ist,  ist die andere Frage.

            Doch, sie existiert, bloß waren nur die guestbook[$i]['name']-Felder belegt, die anderen waren Dank Schusseligkeit in $guestook[...] ;-)

            Ich zitiere dich noch mal:

            $guestook[$i]['name'] = $werte[0];

            Das steht eindeutig was mit $guestook, oder etwa nicht?

            Nein, so viel Traffic habe ich lange nicht, veilleicht zehn(!) Aufrufe (des Forums) am Tag... da macht das wohl keine Probleme...

            Achsooo. Ähm, tschuldige, sag mal, ich sehe da nur ein Board... Tztztzt...

            Grüße,

            Christian

            --
            Ich bitte darum, dass ein Themenbereich (BARRIEREFREIHEIT) eingerichtet wird.
            1. Hi

              Ja, aber wie willst das das denn ausschneiden, wenn du nicht weißt, welcher Teil "fehlt"?
              Trial & Error? *scnr* ;-)
              Ich wollte damit nur sagen, dass es _möglich_ ist. Ob es _sinnvoll_ oder _durchführbar_ ist,  ist die andere Frage.

              Nein, da hast du mich falsch verstanden. Ich müsste die gesamte Session lesen können, nicht nur das entsprechende Stück. Das ginge nur, wenn (serialisierte) Session-Dateien äuquivalent zu gleichen, aber manuell serialisierten, Daten wären. Das sind sie nunmal aber nicht. Für mich ist da einfach an der falschen Stelle gespart worden.

              Doch, sie existiert, bloß waren nur die guestbook[$i]['name']-Felder belegt, die anderen waren Dank Schusseligkeit in $guestook[...] ;-)

              $guestook[$i]['name'] = $werte[0];
              Das steht eindeutig was mit $guestook, oder etwa nicht?

              Ja ist gut, das Script war nicht grade mein bestes... >;)

              Nein, so viel Traffic habe ich lange nicht, veilleicht zehn(!) Aufrufe (des Forums) am Tag... da macht das wohl keine Probleme...

              Achsooo. Ähm, tschuldige, sag mal, ich sehe da nur ein Board... Tztztzt...

              Ja.... noch *grrr*

              Fabian

              1. Moin!

                Nein, da hast du mich falsch verstanden. Ich müsste die gesamte Session lesen können, nicht nur das entsprechende Stück. Das ginge nur, wenn (serialisierte) Session-Dateien äuquivalent zu gleichen, aber manuell serialisierten, Daten wären. Das sind sie nunmal aber nicht. Für mich ist da einfach an der falschen Stelle gespart worden.

                Du kannst Funktionen registrieren, die anstatt der Standard-Funktionen das Speichern, Laden und löschen von Session-Daten übernehmen. Dann kannst du deine eigenen Datenformate für die Session-Daten definieren bzw. den Speicherort beispielsweise auch in eine Datenbank verlagern. Alles gar kein Problem.

                Ich denke nur, es ist ungünstig, ohne obige Maßnahme in einen internen Prozess (Session-Handling) einzugreifen. Warum sollte man das wollen?

                - Sven Rautenberg

                --
                "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
                1. Hi Sven

                  Nein, da hast du mich falsch verstanden. Ich müsste die gesamte Session lesen können, nicht nur das entsprechende Stück. Das ginge nur, wenn (serialisierte) Session-Dateien äuquivalent zu gleichen, aber manuell serialisierten, Daten wären. Das sind sie nunmal aber nicht. Für mich ist da einfach an der falschen Stelle gespart worden.
                  Du kannst Funktionen registrieren, die anstatt der Standard-Funktionen das Speichern, Laden und löschen von Session-Daten übernehmen. Dann kannst du deine eigenen Datenformate für die Session-Daten definieren bzw. den Speicherort beispielsweise auch in eine Datenbank verlagern. Alles gar kein Problem.
                  Ich denke nur, es ist ungünstig, ohne obige Maßnahme in einen internen Prozess (Session-Handling) einzugreifen. Warum sollte man das wollen?

                  Für den Fall, das eine "normale" Session nicht möglich ist und ich z.B. per 401-Auth die gleichen Daten wie für Session verwenden möchte. Kannst du mir saqgen, wo ich mehr darüber finde?

                  Fabian

                  1. Moin!

                    Ich denke nur, es ist ungünstig, ohne obige Maßnahme in einen internen Prozess (Session-Handling) einzugreifen. Warum sollte man das wollen?
                    Für den Fall, das eine "normale" Session nicht möglich ist und ich z.B. per 401-Auth die gleichen Daten wie für Session verwenden möchte. Kannst du mir saqgen, wo ich mehr darüber finde?

                    Wieso sind normale Sessions bei HTTP-Auth nicht möglich? Sessions sind eigentlich immer möglich, vermutlich hast du bislang nur nicht dran gedacht, ob es wirklich geht.

                    Wenn du mal genauer erzählst, was du willst, gibts vielleicht eine einfache Lösung.

                    - Sven Rautenberg

                    --
                    "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
                    1. Hi

                      Ich denke nur, es ist ungünstig, ohne obige Maßnahme in einen internen Prozess (Session-Handling) einzugreifen. Warum sollte man das wollen?
                      Für den Fall, das eine "normale" Session nicht möglich ist und ich z.B. per 401-Auth die gleichen Daten wie für Session verwenden möchte. Kannst du mir saqgen, wo ich mehr darüber finde?

                      Wieso sind normale Sessions bei HTTP-Auth nicht möglich? Sessions sind eigentlich immer möglich, vermutlich hast du bislang nur nicht dran gedacht, ob es wirklich geht.

                      Nein, es geht nicht so, wie ich möchte - glaub es mir. Wir haben alles durchprobiert, aber es geht ohne die Implementierung von ordentlichen Serialisierungen in der Session nicht - oder extrem imperformant.

                      Fabian

                  2. Hallo Fabian!

                    Für den Fall, das eine "normale" Session nicht möglich ist und ich z.B. per 401-Auth die gleichen Daten wie für Session verwenden möchte. Kannst du mir sagen, wo ich mehr darüber finde?

                    Kann mir mal einer von Euch erklären was genau die HTTP-Authentifizierung mit Sessions zu tun hat?
                    Wenn ich Eure Problematik bis hierher richtig verstanden habe besteht Euer Problem("normale Sessions sind nicht möglich") darin, dass Ihr die Übergabe der SessionID mit den dafür vorgesehen Mechanismen nicht vertaut.
                    In meinen Augen hat die Authentifizierung zunächst nichts mit der Session zu tun. Man kann entweder das eine verwenden, oder das andere, oder beides.
                    Aber so ganz verstehe ich Euch nicht. Wie übergebt Ihr denn die SessionID?  Oder setzt Ihr die SessionID = PHP_AUTH_USER? Ihr müssst für eine Authentifizierung sowieso auf das File-System zugreifen, da macht es nicht viel wenn man das durch einen eigenen Session_Handler ein weiteres mal tut.
                    Was nicht in meinen Kopf will ist folgendes:
                    Entweder Ihr habt einen Weg gefunden die SessionID super-sicher zu übertragen, dann verstehe ich die Notwendigkeit auf $_SESSION zu verzichten allerdings nicht, oder Ihr habt eben das nicht geschafft, aber damit erübrigt sich der komplette Session-Mechanismus.

                    Entweder ich benutze den Mechanismus und dann auch seine Schnittstellen, wenn dieser Mechanismus aber meinen Anforderungen nicht genügt schreibe ich einen eigenen, oder wenn es am Handler liegt einen eigenen Handler. _Gerade_ Seiten wo man sich mit HTTP-Authentification anmelden muß sind normalerweise nicht _sooooo_ stark frequentiert, dass der Performance-Verlust durch einen eigenen Handler da groß ins Gewicht fällt.

                    Viele Grüße
                    Andreas

                    PS: siehe auch [pref:t=32768&m=177915]

                    1. Hallo zusammen,

                      PHP unterstützt automatische Sessions mit COOKIES, weil das Sinn macht. Es stellt einen Fallbackmechanismus auf "inline-Sessionkennung" zur Verfügung. Der ist nicht so zuverlässig, wie ein Cookie.

                      Die Verwendung von Auth-Crendentials ist für die Sessionverarbeitung durchaus zuverlässig. Leider stellt PHP hierfür keine automatischen Methoden für session_start() und script_shutdown() zur Verfügung. Die muss man sich selber schreiben. Das ist ist Dank fopen(), fread(), fclose(), fwrite(), serialize(), unserialize(), register_shutdown_function() auch kein Problem.

                      Nun gesetzt den fall, man will dem besucher jedesmal die selbe Sessionnummer geben, dann könnte er einen angefangenen Vorgang beim nächsten Mal fortsetzen. Könnte ja sein, dass er das nun vom PC seiner Schwester aus tun muss, die aber aus Prinzip Angst vor Cookies hat (OK, dann sollte er sich viellicht ne andere Schwester suchen *gg*), dann könnte er bei gleichem Format von interner Serialisierung und serialize() die Session auch mit auth übernehmen. Das Dagtenmodell wäre an dieser Stelle nicht gebrochen und man würde von einer "sauberen Lösung" sprechen können.

                      Gesucht wird also, wenn ich Fabian hier mal unterstützen darf, eine Methode, mit der man die Sicherung und Wiederherstellung der Daten bei Session mit dem original session_start() in das Format von serialize()/unserialize() bringen kann. Es wird wohl nichts anderes übrig bleiben, als session_set_save_handler() zu verwenden und für read und write die Funktionen einzusetzen, die man auch für "Auth-Sessions" benutzt. Da kann ich aber leider auch nicht weiterhelfen.

                      (Hinweis: Gesucht werden nicht die ständigen Nörgler, die nie weiterhelfen, sondern nur demotivieren.)

                      Wie kan man bei Benutzung der Funktion dafür sorgen, dass die anderen unangetastet bleiben? Wie heißen die Originalfunktionen? Oder muss man für das Beibehalten nut NULL übergeben? Wer hat da schonmal in den Quelltext reingeschaut?

                      Grüße

                      Tom

                      1. Moin!

                        Nun gesetzt den fall, man will dem besucher jedesmal die selbe Sessionnummer geben, dann könnte er einen angefangenen Vorgang beim nächsten Mal fortsetzen. Könnte ja sein, dass er das nun vom PC seiner Schwester aus tun muss, die aber aus Prinzip Angst vor Cookies hat (OK, dann sollte er sich viellicht ne andere Schwester suchen *gg*), dann könnte er bei gleichem Format von interner Serialisierung und serialize() die Session auch mit auth übernehmen. Das Dagtenmodell wäre an dieser Stelle nicht gebrochen und man würde von einer "sauberen Lösung" sprechen können.

                        Das ist doch eigentlich gar kein Problem. Es _ist_ sogar gar kein Problem, weil ich genau das schon gemacht habe.

                        Der Trick ist, dass man, noch bevor eine Session gestartet wird, erstmal die Anmeldedaten auswertet. Dann guckt man nach, ob diese Anmeldedaten schon eine zugeordnete Session besitzen, und setzt in diesem Fall die Session-ID auf die gespeicherte ID. Und erst _dann_ startet man die Session, welche Prompt alle Session-Variablen lädt und zur Verfügung stellt.

                        Das ganze läuft simpel so ab (zugegeben: PHP 4.0.x):

                        if (Alte Session soll übernommen werden)
                        {
                          session_id($alte_sessionid);
                        }
                        else
                        {
                          session_id($PHPSESSID)
                        }

                        session_start();

                        Aufgemerkt: Der Befehl session_start() überschreibt (zumindest bei register_globals=on) alle Variablen, die in der Session registriert wurden. Man sägt, wenn man sich dumm anstellt, unter Umständen am eigenen Ast. Wenn sich die Variablen hingegen alle in $_SESSION wiederfinden, ist diese Gefahr nicht gegeben.

                        Gesucht wird also, wenn ich Fabian hier mal unterstützen darf, eine Methode, mit der man die Sicherung und Wiederherstellung der Daten bei Session mit dem original session_start() in das Format von serialize()/unserialize() bringen kann. Es wird wohl nichts anderes übrig bleiben, als session_set_save_handler() zu verwenden und für read und write die Funktionen einzusetzen, die man auch für "Auth-Sessions" benutzt. Da kann ich aber leider auch nicht weiterhelfen.

                        Aha, du gehörst also zu den "wir"? :)

                        - Sven Rautenberg

                        --
                        "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
                        1. Hi Sven, Hi Thomas!

                          Der Trick ist, dass man, noch bevor eine Session gestartet wird, erstmal die Anmeldedaten auswertet. Dann guckt man nach, ob diese Anmeldedaten schon eine zugeordnete Session besitzen, und setzt in diesem Fall die Session-ID auf die gespeicherte ID.

                          Und wie macht man das ohne die Session zu starten? Wo genau guckst Du was nach? Ich wäre jetzt auf die Idee gekommen, genau wie Du erstmal die Anmeldung zu überprüfen, aber das lasse ich vom Apachen erledigen, so habe ich einen rundum-Schutz und bin unabhängiger von PHP. Also wenn das Script dann also geladen wird kann ich davon ausgehen dass die Zugangsdaten gültig sind. Dann hätte ich folgende Idee:
                          Ich weise einfach den Usernamen als Session zu oder ist das blöd?
                          Einfach
                          session_id($_SERVER["REMOTE_USER]);
                          session_start();

                          Dann übernimmt der Session-Mechanismus den Rest, er legt entweder eine neue Session an oder greift auf die vorhandene zu, und ich habe schön meine sicheren HTTP-AUTH Daten die ich zur Wiedererkennung verwende. Das sollte doch gut funktionieren, oder? Dann müßte man nur Cookies etc alles abschaltenn. Wenn man dann für die Session-Files ein ganz eigenes Verzeichnis erstellt, hat man hierüber sogar ohne Session zu starten Zugriff auf die Daten, man kann schon an den Dateinamen sehen welche User eingeloggt sind, etc, man könnte sich sogar eben den Quellcode ansehen wie das Parsen der Session-Datei aussieht, ich habe auch mal kurz gesucht, ist aber ein wenig Komplex das ganze ;-)

                          Das ganze läuft simpel so ab (zugegeben: PHP 4.0.x):

                          if (Alte Session soll übernommen werden)
                          {
                            session_id($alte_sessionid);

                          wo hast Du die alte SessionID her?

                          }
                          else
                          {
                            session_id($PHPSESSID)
                          }

                          kann man den Else-Teil nicht weglassen?

                          session_start();

                          Nun gesetzt den fall, man will dem besucher jedesmal die selbe Sessionnummer geben, dann könnte er einen angefangenen Vorgang beim nächsten Mal fortsetzen. Könnte ja sein, dass er das nun vom PC seiner Schwester aus tun muss, die aber aus Prinzip Angst vor Cookies hat (OK, dann sollte er sich viellicht ne andere Schwester suchen *gg*), dann könnte er bei gleichem Format von interner Serialisierung und serialize() die Session auch mit auth übernehmen. Das Dagtenmodell wäre an dieser Stelle nicht gebrochen und man würde von einer "sauberen Lösung" sprechen können.

                          Die Fraeg ist ob der Session-Mechanismus für solche Sachen gedacht ist udn gedacht seoin sollte! Wir wollen ja keine eierlegende WollMilchSau die irgendwie alles ein bisschen aber nichts richtig kann. Für normale Session-Anwendungen ist der Mechanismus so gut wie er ist, wer es anders braucht schreibt sich seinen Handler oder einen eigenen Mechanismus. Und nicht dass Du denkst ich wolle hier Ärger machen oder sowas, ich hatte mich jetzt nur wirklich eingehender mit der Problematik befaßt, und je mehr ich das tue desto sicherer bin ich mir das Du nichtmal einen anderen Handler brauchen solltest!
                          Ich plane nämlöich ebenfalls eine Kombination aus HTTP Auth und Sessions, um ein Objekt mit allen möglichen Daten in der Session zu haben, so dass ich nur einmal pro Besuch alle möglichen Konfig-Files und DB-Einträge wie Rechte, indiv. Menüleiste... laden muß. Wenn ich auf die Daten zugreifen will mach eich das schlicht und einfach mit $_SESSION, ich wüßte nicht wo da ein Problem bestehen könnte!

                          Gesucht wird also, wenn ich Fabian hier mal unterstützen darf, eine Methode, mit der man die Sicherung und Wiederherstellung der Daten bei Session mit dem original session_start() in das Format von serialize()/unserialize() bringen kann.

                          Obwohl ich den Satz jetzt nicht zu 100% verstehe, probiere ich trotzdem: Das Format in der Session-Datei _entspricht_ doch serialize(), oder? Der Unterschied besteht nur darin das Du mit Serialize() immer nur eine Variable behandelst, in der Session stehen nunmal mehrere. In der Session steht das meines Wissens so:
                          bei integer:
                          <var_name>|i:<INT-Wert>;

                          bei string:
                          <var_name>|s:<anzahl zeichen>:"<STRING-Wert>";

                          bei array:
                          <var_name>|a:<anzahl elemente>:{<ELEMENTE mit i,s,o oder a>}

                          bei object:
                          <var_name>|o:<anzahl elemente>:{<ELEMENTE mit i,s,o oder a>}

                          Alles was hinter "<var_name>|" steht entspicht serialize(). Ich habe halt kurz einen Parser gebaut, der alle Buchstaben bis | in einen String schreibt, diesen als Variablennamen verwendet, alles dahinter bis zu einer sich schließender Klammer und wenn dann keine mehr offen ist komplett durch serialize() schickt und das Ergebnis dem zuvor ermittelten Namen zuweist, die andere Variante(für i und s) funktioniert genau so nur das hier statt nach einerm } nach einem ; gesucht wird. Wenn man noch ein bisschen dran feilt kommt am Ende der Session-Array raus ohne die Session gestartet zu haben. Das Problem an meinem Ansatz ist nur, dass wenn irgendeins von den magischen Zeichen in dem serialisierten String vorkommt, dass dann vermutlich einiges daneben geht. Daher müßte man sich einen richtigen Parser schreiben, der auf unserialize() verzichtet und das ganze "manuell" parst. Dürfte auch nicht so wild sein, wie gesagt müßte das ja auch irgendwo im PHP-Quelltext als Vorlage in C stehen, nur sehe ich halt keine Notwendigkeit das zu tun.

                          Es wird wohl nichts anderes übrig bleiben, als session_set_save_handler() zu verwenden und für read und write die Funktionen einzusetzen, die man auch für "Auth-Sessions" benutzt. Da kann ich aber leider auch nicht weiterhelfen.

                          Ich frage mich immer noch warum denn wenn schon der Session-Mechanismus benutzt wird nicht einfach auf $_SESSION zugegriffen wird? Vermutlich bin ich etwas schwer von Begriff, aber ich verstehe es nunmal nicht. Die obige Struktur läßt sich mit einem recht kleinen Script bestimmt gut parsen, ich hatte das in Ansätzen probiert, das geht sicher genau so gut wie PHP das selbst macht.

                          Viele Grüße
                          Andreas

                          1. Moin!

                            Und wie macht man das ohne die Session zu starten? Wo genau guckst Du was nach? Ich wäre jetzt auf die Idee gekommen, genau wie Du erstmal die Anmeldung zu überprüfen, aber das lasse ich vom Apachen erledigen, so habe ich einen rundum-Schutz und bin unabhängiger von PHP. Also wenn das Script dann also geladen wird kann ich davon ausgehen dass die Zugangsdaten gültig sind. Dann hätte ich folgende Idee:
                            Ich weise einfach den Usernamen als Session zu oder ist das blöd?
                            Einfach
                            session_id($_SERVER["REMOTE_USER]);
                            session_start();

                            Naja, das ist mir nur rein vom Gefühl her zu unsicher. Der Benutzer kann sich regulär einloggen, und dann, da er den Benutzernamen des Kollegen kennt, dessen Identität annehmen. Man müßte also immer prüfen, ob REMOTE_USER und registrierte Session zueinander passen. Klingt nicht wirklich gut.

                            Das ganze läuft simpel so ab (zugegeben: PHP 4.0.x):

                            if (Alte Session soll übernommen werden)
                            {
                              session_id($alte_sessionid);
                            wo hast Du die alte SessionID her?

                            Die kommt aus der Datenbank, in der auch Username und Passwort drinstehen. Die schreibe ich da rein, wenn eine _neue_ Session gestartet wurde, und sie wird gelöscht, wenn der Benutzer sich echt ausloggt. Außerdem kriegt die Datenbank noch einen Timestamp des Einloggens mit, so dass man auch zeitlich irgendwann eine neue Session beginnen könnte - sofern das gewünscht ist.

                            }
                            else
                            {
                              session_id($PHPSESSID)
                            }
                            kann man den Else-Teil nicht weglassen?

                            Keine Ahnung, so genau hab' ich mir das nicht angeschaut. Ich hatte das Gefühl, entweder das eine oder das andere machen zu müssen. :)

                            - Sven Rautenberg

                            --
                            "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
                            1. Hallo Sven!

                              Ich weise einfach den Usernamen als Session zu oder ist das blöd?
                              Einfach
                              session_id($_SERVER["REMOTE_USER]);
                              session_start();

                              Naja, das ist mir nur rein vom Gefühl her zu unsicher.

                              Aber wieso? Es gibt nichst viel sichereres als den HTTP-AUTH schutz des Apachen. Solange dieser läuft sollte das auch funktionieren, und wenn nicht gehen auch keine Scripte raus. Der Ganze MEchanismus kommt ja nur zum Tragen wenn der User sich bereust erfolgreich eingeloggt hat.

                              Der Benutzer kann sich regulär einloggen, und dann, da er den Benutzernamen des Kollegen kennt, dessen Identität annehmen.

                              wie? Dann müßte er sich entweder mit dem Passwort des Kollegen einloggen können, oder meine Umgebungsvariablern manipulieren - wie soll das gehen? Wenn er das kann kann er _alles_ manipulieren, auch PHP_AUTH_USER...

                              Man müßte also immer prüfen, ob REMOTE_USER und registrierte Session zueinander passen. Klingt nicht wirklich gut.

                              Wieso? Ich es gibt jeden User nur einmal. Wenn sich ein User einloggt bekommt er eine Session mit dem Usernamen als Session_ID, was muss ich da prüfen? Wenn ein neuer Request von dem REMOTE_USER kommt, dann wird die Session halt wieder übernommen. Was soll ich da noch prüfen?

                              wo hast Du die alte SessionID her?
                              Die kommt aus der Datenbank, in der auch Username und Passwort drinstehen. Die schreibe ich da rein, wenn eine _neue_ Session gestartet wurde, und sie wird gelöscht, wenn der Benutzer sich echt ausloggt. Außerdem kriegt die Datenbank noch einen Timestamp des Einloggens mit, so dass man auch zeitlich irgendwann eine neue Session beginnen könnte - sofern das gewünscht ist.

                              Hm, vielleicht doch so. Aber was habe ich davon die Session_id zu speichern und vorher zu überprüfen? Das kann ich mir doch sparen wenn ich direkt den Benutzernamen verwende! Wie gesagt wird der dann nicht übertragen, Cookies und Rewriting ist beides abgeschaltet, die "Session_ID" wird also nur über den Auth-Header des Browsers übertragen, und zwar als Benutzername. Vielleicht sollte ich dann aber den HTTP-Auth Mechanismus doch mit PHP einbinden, dann habe ich im Script die Kontrolle und kann dort alles abfragen und sicher gehen das die User-Daten valide sind.

                              Viele Grüße und schöne Weihnachten!
                              Andreas

                              1. Moin!

                                Ich weise einfach den Usernamen als Session zu oder ist das blöd?
                                Einfach
                                session_id($_SERVER["REMOTE_USER]);
                                session_start();

                                Naja, das ist mir nur rein vom Gefühl her zu unsicher.
                                Aber wieso? Es gibt nichst viel sichereres als den HTTP-AUTH schutz des Apachen. Solange dieser läuft sollte das auch funktionieren, und wenn nicht gehen auch keine Scripte raus. Der Ganze MEchanismus kommt ja nur zum Tragen wenn der User sich bereust erfolgreich eingeloggt hat.

                                Die Sicherheit, dass niemand fremde Sessions übernehmen kann, rührt daher, dass die Session-ID nicht geraten werden kann. Wenn du als Session-ID den Benutzernamen nimmst, kann ein anderer Benutzername durchaus geraten werden. Diesem Szenario würde ich lieber von Anfang an aus dem Weg gehen.

                                Es ist doch nichts dabei, eine echte, normale Session-ID zu benutzen. Die ist doch zu nichts nutze außer die Session zu identifizieren. Natürlich muß man in den Accountdaten des Benutzers speichern, welche Session-ID er hat, aber das ist IMO gut so.

                                Der Benutzer kann sich regulär einloggen, und dann, da er den Benutzernamen des Kollegen kennt, dessen Identität annehmen.
                                wie? Dann müßte er sich entweder mit dem Passwort des Kollegen einloggen können, oder meine Umgebungsvariablern manipulieren - wie soll das gehen? Wenn er das kann kann er _alles_ manipulieren, auch PHP_AUTH_USER...

                                Wenn er die Anmeldeseite erfolgreich überwunden hat, ist er gegenüber dem System authentifiziert und hat eine ihm zugeordnete Session. Wenn er die Session-ID ändert, indem er am Cookie schraubt oder den URL-Parameter ändert, dann ist er weiterhin als der alte User authentifiziert, die zugehörige Session ist aber die des Kollegen.

                                Oder habe ich ein Detail übersehen?

                                - Sven Rautenberg

                                --
                                "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
                                1. Hi!

                                  Wenn er die Anmeldeseite erfolgreich überwunden hat, ist er gegenüber dem System authentifiziert und hat eine ihm zugeordnete Session.

                                  Wenn er sich authentifiziert dann mit _seinen_ Zugangsdaten. Somit bekommt die SessionID seinen Benutzernamen als Wert. Er _kann_ überhaupt keine andere Session übernehmen, denn die SessionID wird _nicht_ extra übertragen sondern unterdrückt, der Browser sendet doch sowieso jedesmal die HTTP-Authentification Header, wenn User und Pass gültig sind kommt der Request bis zum Script durch und dort wird entsprechend dem REMOTE_USER auf die Session mit dem REMOTE_USER als Session_ID zugegriffen. Das _kann_ er nicht fälschen, er müßte schon einen anderen Header senden. Das geht aber normalerweise nur über das HTTP-AUTH Fenster des Browsers. Hier müßte er user _UND_ pass eingeben um nicht vom Apachen abgewiesen zu werden. Auch wenn der eine manuellen Header schickt reicht das Schicken des Usernamen des Kollegen nicht aus, er braucht auch dessen Passwort, und wenn er das hat ist dessen Account mit keiner Technik der Welt mehr zu schützen. Und da die Trennung von Authentifizierung und der so davon abhängigen Session-Vergabe vielleicht doch irgendwelche Risiken birgt, würde ich die Authentifizierungs-Überprüfung vom Apachen in das PHP-Script verlagern, also würde ich am Anfang des Scriptes die PHP_AUTH_USER und PHP_AUTH_PASS prüfen, und bei Erfolg die session_id($PHP_AUTH_USER) starten.
                                  Deine Bedenken kann ich bisher nicht verstehen. Es geht mir hier um einen Spezialfall wo sowieso per HTTP-AUTH eingeloggt wird. Auf die oben geschilderte Weise müßte das doch _sehr_ sicher sein! Verstehe nicht wo da ein Problem auftreten könnte!

                                  Oder habe ich ein Detail übersehen?

                                  ich hoffe :-)

                                  Mal ein Beispiel:

                                  <?php
                                    if (!isset($_SERVER['PHP_AUTH_USER'])) {
                                      header('WWW-Authenticate: Basic realm="My Realm"');
                                      header('HTTP/1.0 401 Unauthorized');
                                      echo 'Text to send if user hits Cancel button';
                                      exit;
                                    } else {
                                          $userarray = load_users_into_array();
                                          if($userarray[$_SERVER['PHP_AUTH_USER']]== $_SERVER['PHP_AUTH_PW'] && in_array($userarray,$_SERVER['PHP_AUTH_USER']){
                                              session_id($_SERVER['PHP_AUTH_USER']);
                                              session_start();
                                          }
                                    }
                                  ?>

                                  Oder baue ich mir so eine große Sicherheitslücke ein? Ich zumindest sehe da nichts dergleichen.

                                  Viele Grüße
                                  Andreas

                2. Hi zusammen,

                  Du kannst Funktionen registrieren, die anstatt der Standard-Funktionen das Speichern, Laden und löschen von Session-Daten übernehmen. Dann kannst du deine eigenen Datenformate für die Session-Daten definieren bzw. den Speicherort beispielsweise auch in eine Datenbank verlagern. Alles gar kein Problem.

                  Den Session-Save-Handler umzustellen ist ja eine Maßnahme, die die Performace erheblich verschlechtern kann. Es wäre sinnvoller, die PHP-Entwickler würden für Ihre 5er Version eine Harmonisierung zwischen serialize() und der intrnen save-Funktion herbeiführen.

                  Frohes Fest wünsche ich

                  Liebe Grüße aus http://www.braunschweig.de

                  Tom

                  --
                  Intelligenz ist die Fähigkeit, aus Fehlern Anderer zu lernen und Mut die, eigene zu machen.
          2. Hi

            Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.

            Ich habe es gerade mal aus Spaß probiert, ein durch dei Session-Funktion serialisierter multidimensionaler Array sieht _exakt_ so aus wie bei serialize(). Alle Angaben sind gleich. Der einzige Unterschied ist das in der Session vorer noch der Name in Form von name| gespeichert wird und mehrere Variablen durch ; getrennt in der Datei stehen.

            Ja, aber wie willst das das denn ausschneiden, wenn du nicht weißt, welcher Teil "fehlt"?

            Das weiß die Session-Funktion ebensowenig. Naja, ich habe mal kurz probiert ob das mit unserialize klappt, das tut es, nur ist es IMHO umständlicher als das komplett zu parsen, außerdem hatte ich keine Lust das ganze zu perfektionieren, es funktioniert nur grob:

            $input = 'zaehler|i:25;fruits|a:3:{s:7:"früchte";a:3:{s:1:"a";s:6:"Orange";s:1:"b";s:6:"Banane";s:1:"c";s:5:"Apfel";}s:7:"nummern";a:6:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;}s:6:"löcher";a:3:{i:0;s:7:"erstens";i:5;s:8:"zweitens";i:6;s:8:"drittens";}}map|a:4:{s:7:"version";i:4;s:2:"OS";s:5:"Linux";s:7:"Sprache";s:8:"englisch";s:10:"short_tags";b:1;}array|a:5:{i:0;i:7;i:1;i:8;i:2;i:0;i:3;i:156;i:4;i:-10;}str|s:50:"sadasddasd9ß490q 0ßw oadölk dökö erp89p23jöo köa";int|i:234234234;';

            for($i=0,$klammer=0,$len=strlen($input);$i<=$len;$i++){
                if ($input{$i} == "{") {
                 $klammer++;
              $string .= $input{$i};
             }
             else if ($input{$i} == "}") {
                 $klammer--;
              $string .= $input{$i};
              if($klammer == 0) {
               $mySESSION[$last_name] = unserialize($string);
                  $string = "";
              }
             }
             else if ($input{$i} == "|") {
                    $mySESSION[$string] = "";
              $last_name = $string;
              $string = "";
             }
             else if ($klammer == 0 && $input{$i} == ";") {
                 if(substr($string,0,1) == "i") {
                  $mySESSION[$last_name] = substr($string,2);
              }
              else if(substr($string,0,1) == "s") {
                  $mySESSION[$last_name] = unserialize($string);
              }
              $string = "";
             }
             else {
                 $string .= $input{$i};
             }
            }

            echo "<pre>mySession:\n";
            print_r($mySESSION);
            echo "</pre>";

            Wie gesagt, im nachhinein finde ich das da oben gruselig. Aber ich bleibe dabei => warum soll man das nicht einfach dem Session-Mechanismus überassen? Und bisher konntet Ihr auch nicht wirklich begründen, warum die Entwicker von PHP irgendwas an diesem Mechanismus ändern sollten. Wenn einer doch irgendwie an die Daten muß soll er gefälligst in den Quelltext gucken und die dortige Parse-Funktion für die Session-Dateien übernehmen, wobei ich mir sicher bin das ihr das in Wirklichkeit gar nicht wollt/braucht.

            Grüße
            Andreas

      2. Hallo Fabian!

        Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.

        Und warum sollte man das wollen? Wozu gibt es $_SESSION?

        Grüße
        Andreas

        1. Hi

          Widerspruch, das ganze ist bei Sessions höchst unsauber gemacht, wie wir neulich herausgefunden haben, bei Sessions wird nämlich völlig unnötigerweise die Angabe, dass es sich beim Inhalt des serialisierte String um ein assoziatives array handelt weggelassen. Würde das da stehen könnte man mit unserialize eine Session-Datei auslesen. Geht aber nicht.
          Und warum sollte man das wollen? Wozu gibt es $_SESSION?

          siehe unten. erst den ganzen thread lesen ;-)
          Ich habe meine Gründe.

          Fabian

          1. Hi Fabian!

            Und warum sollte man das wollen? Wozu gibt es $_SESSION?
            siehe unten. erst den ganzen thread lesen ;-)

            wirklich schlauer als vorher bin ich aber immer noch nicht!

            Ich habe meine Gründe.

            welche? Entweder ich verwende den Session-Mechanismus und dann auch $_SESSION, oder ich verwende einen eigenen Session-Mechanismus, oder ich  schreibe meinen eigenen Session-Handler. Das ist IMHO alles was man brauchen könnte. Wenn ich den Session-Mechanismus verwende verwende ich auch die hierfür vorgesehene Zugriffsweise, alles andere macht nur Probleme. Und ich wüßte keinen Fall wo man $_SESSION nicht verwenden könnte, denn wenn das nicht geht wird der ganze Mechanismus nicht gehen bzw. ist ungeeignet.
            Und das der eigene Handler unperformanter als der Session-Mechanismus ist - klar, aber wieviel? Performance ist nicht alles und ob man in diesem Sonderfall unbedingt auf jede 1/1000stel Sekunde gucken muß weiß ich nicht.

            Grüße
            Andreas