session_start verträgt sich nicht mit POST- und Feldübergabeprüf
Runtop
- php
Hallo an alle,
ich entwerfe gerade ein Affenformular (Kontaktformular) und zur normalen Eingabeüberprüfung benutze ich auch eine POST- sowie Feldübergabeprüfung.
Das heißt, mit count vergleicht das Script was ankommt und ob es mit dem Array sowie Count angaben übereinstimmt.
Mein Problem liegt bei der session_start.
Wenn ich das Formular beim ersten mal öffne, teils befülle und dann absende dann gibt das Script als echo folgendes aus: POST stimmt nicht und Stimmt nicht mit Array überein
Normalerweise wird das Script mit exit(); abgebrochen, habe es aber jetzt weggelassen!
Wenn ich das Formular schließe und wieder neu öffne, wieder neu befülle und dann absende habe ich das Problem nicht mehr!
Sollte ich aber den Browser (egal ob IE oder FF) schließen, die vollständigen Temporären Internetdateien (Cookies und Dateien) löschen, dann fängt das Problem wieder von vorne an.
Auszug aus dem Code (etwas gekürzt):
session_start(); // steht bei beginn der Seite ganz oben als erstes!
if (isset($_POST['absenden'])) {
$formElements=array('lala',0,1,2,3,4,5,6,7,8,9,10,
usw.);
if (count($_POST)!=33 OR count($_POST['lala'])!=11)
{
echo "POST stimmt nicht";
session_unset();
}
$postElements=array_keys($_POST);
foreach($_POST as $element)
{
if (is_array($element))
$postElements=array_merge($postElements,array_keys($element));
}
$formElementsDif=array_diff($postElements,$formElements);
$postElementsDif=array_diff($formElements,$postElements);
if (count($formElementsDif)>0 OR count($postElementsDif)>0)
{
echo "Stimmt nicht mit Array überein";
session_unset();
}
Ich hoffe dass Ihr mir ein wenig weiterhelfen könnt!
Danke.
Runtop
Hello,
Ich hoffe dass Ihr mir ein wenig weiterhelfen könnt!
Klar, gerne.
Also erstmal die Ursache:
es liegt mit 99% Wahrscheinlichkeit an der automatischen Sessionorganisation von PHP. Wenn mann die Seite das erste Mal aufruft, also vom Browser noch kein Session-Parameter mit dem Request mitgesendet wurde, dann baut PHP (bei Standardeinstellung) in jedes Formular ein <hidden>-Element ein mit der neuen Session-ID.
Wie kannst Du das feststellen?
Lasse Dir das $_POST-Array zum Debuggen ausgeben
echo "<pre>\r\n";
echo htmlspecialchars(print_r($_POST,1));
echo "</pre>\r\n";
Was machst Du falsch?
Du _zählst_ die per POST übergebenen Paramter, obwohl die Anzahl vollkommen irrelevant ist.
Wie kannst Du es besser machen?
Die Liste der notwendigen Felder mit dem POST-Array vergleichen
Du baust ein Vergleichsarray mit den Namen aller Parameter auf
$_expected['name'][$i] Name des POST-Paramters
$_expected['duty'][$i] Ist er Pflicht?
$_expected['complete'][$i] Muss er ergänzt werden, wenn er fehlt?
$_expected['default'][$i] was ist der Default bei Ergänzung?
... weitere z.B. für valid-Prüfung usw.
$_expected['checked'][$i] POST-Array und Vorgabe bereits verglichen
dann fährst Du das $_POST-Array mit foreach() ab und vergleichst die Vorgaben in $_expected. Alle geprüften werden mit ['checked'] = true gekennzeichnet. Diejenigen, die dort nicht enthalten sind, führen zum Prüfungsfehler!
Wenn die Prüfung bis hierher ok war, machst Du die Gegenprobe, indem Du mit foreach() und array_filter() die ['checked']-Spalte des $_expected-Arrays abfährst und alle diejenigen, die noch nicht checked wurden, nach eingetragenen Vorgaben (z.B. Default) abarbeitest.
Auch hierbei führt ein fehler zum Prüfungsfehler!
So verhinderst Du, dass Du unerwartete Parameter erhalten kannst und auch, dass welche fehlen. Außerdem kannst Du diejenigen, die nur im Auswahlfall mitkommen (radio, checkbox, select, ...) im POST-Array ergänzen, sodass ein Datenbankupdate dann später nach Schema F ablaufen kann.
Wenn Du noch Fragen hast zum Verfahren, dann melde dich nochmal.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg

Hello Tom,
vielen Dank für deine Hilfe sowie Erklärungen!
Das beim ersten Seitenaufruf PHP ein verstecktes Element in das Formular eingebaut wird habe ich schon befürchtet und mit deiner echo Ausgabe wurde mir dieses auch bestätigt. Dieses Element ist nach dem zweiten öffnen nicht mehr Sichtbar, es wird quasi wieder gelöscht.
Nicht das du mich jetzt falsch verstehst, ich bin für jeden Ratschlag offen, aber würde es nicht reichen wenn ich jetzt einfach ein hiddenfield mit dem Namen PHPSESSID im Formular erstelle und den Wert leer lasse?
Der Feldwert wird nie befüllt (auf jedenfalls nicht durch PHP oder mein Script). Würde ich damit eine Sicherheitslücke aufreißen?
Danke für deine Antwort!
Gruß, Runtop
Hello,
Nicht das du mich jetzt falsch verstehst, ich bin für jeden Ratschlag offen, aber würde es nicht reichen wenn ich jetzt einfach ein hiddenfield mit dem Namen PHPSESSID im Formular erstelle und den Wert leer lasse?
Nicht wirklich.
Du könntest die Session-Strategie von PHP umstellen, bevor Du die Session startest.
http://de.php.net/manual/en/book.session.php
http://de.php.net/manual/en/function.ini-set.php
http://de.php.net/manual/en/session.configuration.php#ini.session.use-only-cookies
session.use_only_cookies = 1
Dann würde PHP diese versteckten Elemente nicht mehr einbauen in die Formulare, da Sessions nur noch über Cookies vereinbart würden.
Oder Du lässt einfach die Prüfung weg, in der Du die Post-Paramter zählst, denn die taugt ja sowieso nichts, wenn Du nicht prüfts, ob es auch die erwarteten Post-Parameter sind, also zumindest diejenigen, mit den passenen Namen.
Und wenn Du später mal Checkboxen, Radio-Groups oder Select-Elemente einbaust in die Formulare, taugt doch die Anzahlfeststellung als methode sowieso nicht mehr.
Wenn Du es bequem und unsicher lösen willst, ist bei Dir also weniger mehr :-)
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg

Session nur über Cookies halte ich persönlich für nicht akzeptabel.
Man muss ja damit rechnen dass ein User Cookies gesperrt hat.
Unsicher soll es auch nicht sein, ganz klar! :-)
Ich versuche jetzt mal nach deinen ersten vorgaben was zu erstellen, weiß aber noch nicht wie ich da genau ansetzen soll! Also fange ich mal ganz langsam an und hoffe dass du keinen Hals bekommst
Also als erstes ein Array mit den Namen aller POST Parameter erstellen.
$formElements=array('PHPSESSID',
'lolipop',
'lala',0,1,2,3,4,5,6,7,8,9,10,
'vorname',
'nachname',
'strasse',
'hausnummer',
'plz',
'ort',
'land',
'telefon',
'fax',
'email',
'email-bestaetigung',
'betreff',
'nachricht',
'uhreins',
'uhrzwei',
'uhrdrei',
'uhrvier');
Gruß, Runtop
Hello,
Session nur über Cookies halte ich persönlich für nicht akzeptabel.
Man muss ja damit rechnen dass ein User Cookies gesperrt hat.
Dachte ich mir.
Unsicher soll es auch nicht sein, ganz klar! :-)
Umso besser.
Ich versuche jetzt mal nach deinen ersten vorgaben was zu erstellen, weiß aber noch nicht wie ich da genau ansetzen soll! Also fange ich mal ganz langsam an und hoffe dass du keinen Hals bekommst
Also als erstes ein Array mit den Namen aller POST Parameter erstellen.
Bitte binde sie gleich in einem Subarray mit ihrer Eigenschaft "name"
$formElements['name']=array('PHPSESSID',
'lolipop',
'lala',0,1,2,3,4,5,6,7,8,9,10,
'vorname',
'nachname',
'strasse',
'hausnummer',
'plz',
'ort',
'land',
'telefon',
'fax',
'email',
'email-bestaetigung',
'betreff',
'nachricht',
'uhreins',
'uhrzwei',
'uhrdrei',
'uhrvier');
Denn Du wirst jetzt als nächstes gleich ein weiteres Subarry für "duty" oder "required" oder wir auch immer Du die Eigensschaft für die Pflichtfelder nennst ...
$formElements['required'][0] = true;
$formElements['required'][1] = true;
$formElements['required'][2] = false;
...
Die Indices müssen dann korrespondieren.
Zur Kontrolle kannst Du Dir das erste Array auch nochmal anzeigen lassen:
echo "<pre>\r\n";
echo htmlspecialchars(print_r($formElements['name'],1));
echo "</pre>\r\n";
Ich habe mir für die Erstellung der Form-Definitionslisten (dieses Arrays) ein kleines Tool gebastelt. Da kann ich das dann alles in einem Grid eingeben und das/die Definitionsarrays wird/werden automatisch erzeugt.
Durch einen andern Thread bin ich aber gestern noch auf eine Erweiterungsmöglichkeit gestoßen, die ich da noch einbauen will :-)
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg

Hello,
»» Session nur über Cookies halte ich persönlich für nicht akzeptabel.
»» Man muss ja damit rechnen dass ein User Cookies gesperrt hat.Dachte ich mir.
So sollte es ja auch sein um die User nicht zu verärgern! :-)
Bitte binde sie gleich in einem Subarray mit ihrer Eigenschaft "name"
Denn Du wirst jetzt als nächstes gleich ein weiteres Subarry für "duty" oder "required" oder wir auch immer Du die Eigensschaft für die Pflichtfelder nennst ...
Ah, der Groschen fällt, zwar langsam aber jetzt verstehe ich so einigermaßen was du in der ersten antwort damit gemeint hast!
Ich gehe aber jetzt erst einmal was Essen und bedanke mich nochmals für die guten Erklärungen. Weiter ausprobieren werde ich morgen und hoffe das ich ohne Hilfe auskomme.
Also nochmals vielen dank und einen schönen Feierabend an dich!
Gruß, Runtop
Hallo Tom und andere Teilnehmer des Forums,
ich kämpfe schon seit Stunden mit dem Script, oder umgekehrt. :-)
Jetzt habe ich das Problem beim vergleich, und zwar bei den Formularfeldern.
Einige Formularfelder haben den Namen lala[0], lala[1], lala[2] etc.
Der folgenden Codeschnipsel gibt mir aus das die POST übergabe nicht mit dem Array übereinstimmt.
$_expected['postlisteerlaubt']=array('lolipop',
'lala',0,1,2,3,4,5,6,7,8,9,10,
'vorname',
'nachname',
'strasse',
'hausnummer',
'plz',
'ort',
'land',
'telefon',
'fax',
'email',
'email-bestaetigung',
'betreff',
'nachricht',
'uhreins',
'uhrzwei',
'uhrdrei',
'uhrvier',
'Eingabefeld13');
foreach($_POST as $_expected['postankommend'])
if (is_array($_expected['postankommend']))
{
$result = array_diff($_expected['postankommend'], $_expected['postlisteerlaubt']);
print_r($result);
}
Das ist die Ausgabe:
Array ( [0] => [1] => [2] => [3] => [4] => [5] => [6] => [7] => [8] => [9] => [10] =>)
Es dürfte aber gar nichts dort stehen!
Hättest du einen tipp für mich, ich habe schon gegoogelt wie ein blöder (Behandlung Array in Array etc. eingegeben) war aber nie das richtige dabei.
Danke.
Gruß, Runtop
Hallo Tom und andere Teilnehmer des Forums,
habe es jetzt herausgefunden warum es mit den Formularfeldern die so benannt wurden, lala[1], lala[2] etc. nicht funktioniert hat!
Zum $_POST-Array gehört nicht nur foreach() sondern auch array_keys() der alle Schlüssel eines Arrays liefert und array_merge() das wiederum mehrere Arrays zu einem Array verbindet.
Beispiel:
$_expected['allposts']=array_keys($_POST);
foreach($_POST as $element)
{
if (is_array($element))
$_expected['allposts']=array_merge($_expected['allposts'],array_keys($element));
}
Sollte ich nicht richtig argumentiert haben, bitte ich dieses zu verzeihen und um Berichtigung!
Gruß, Runtop