2015-12-11 6 views
9

Ich habe ein paar Monate damit verbracht, eine Anwendung auf einer meiner Domains zu entwickeln. Es ist insgesamt ein einfaches Konzept. Während der Entwicklung habe ich es selbst auf meiner eigenen Domain gehostet, aber vor kurzem hat es zu unserer aktuellen verschoben. Das Problem ist, dass Sitzungen nicht zwischen den Seiten erstellt oder beibehalten werden, und ich kann nicht für das Leben von mir herausfinden, warum.PHP Sitzungen verloren zwischen den Seiten - verhält sich je nach Server unterschiedlich

Entschuldigung für die Wand des Codes unten, aber ich bevorzuge es über eine theoretische Erklärung.

Beginnen wir mit, wie ich meine Session am Anfang jeder Seite beginnen:

function sec_session_start() { 
    $session_name = 'login'; 
    $secure = false; 
    $httponly = true; 

    ini_set('session.use_only_cookies', 1); 
    session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); 
    session_name($session_name); 
    session_start(); 
    session_regenerate_id(); 
} 

Und dann, wie ich überprüfen, ob der Benutzer angemeldet ist Ich habe return x; statt false für die Fehlersuche.. Ich füge das an die Weiterleitungs-URL an.

function login_check($mysqli) { 
if(isset($_SESSION['id'], $_SESSION['login_string'], $_SESSION['type'])) { 
    $id = $_SESSION['id']; 
    $login_string = $_SESSION['login_string']; 

    $user_browser = $_SERVER['HTTP_USER_AGENT']; 

    if($_SESSION['type'] == 1 || $_SESSION['type'] == 2) // Admin user 
    { 

     if ($stmt = $mysqli->prepare("SELECT `password` FROM `users` WHERE `id` = ? LIMIT 1")) { 
      $stmt->bind_param('s', $id); 
      $stmt->execute(); 
      $stmt->store_result(); 

      if($stmt->num_rows == 1) { 
       $stmt->bind_result($password); 
       $stmt->fetch(); 
       $login_check = hash('sha512', $password.$user_browser); 
       if($login_check == $login_string) { 
        return true; 
       } else { 
        return 1; 
       } 
      } else { 
       return 2; 
      } 
     } else { 
      return 3; 
     } 
    } else if($_SESSION['type'] == 3) { // Standard user 
     if($stmt=$mysqli->prepare("SELECT `password` FROM `proj` WHERE `id` = ? LIMIT 1")) 
     { 
      $stmt->bind_param("s", $_SESSION['id']); 
      $stmt->execute(); 
      $stmt->store_result(); 

      if($stmt->num_rows == 1) 
      { 
       $stmt->bind_result($db_key); 
       $stmt->fetch(); 
       $login_check = hash('sha512', $db_key.$user_browser); 
       if($login_check == $login_string) { 
        return true; 
       } else { 
        return 4; 
       } 
      } 
     } 
    } else { 
     return 5; 
    } 
} else { 
    return 6; 
} 
} 

Ich habe zwei Anmeldeseiten, eine für Administratoren und eine für Benutzer.

Admin:

<?php 

ini_set('display_errors','On'); 
error_reporting(E_ALL); 

include_once "../functions.php"; 
include_once "../db_connect.php"; 

sec_session_start(); 

if(login_check($mysqli) === true) { 

header('Location: ../index.php'); 

} 
else 
{ 

// Login form 

} 

Benutzer:

<?php 

ini_set('display_errors','On'); 
error_reporting(E_ALL); 

include_once "../functions.php"; 
include_once "../db_connect.php"; 

sec_session_start(); 

if(login_check($mysqli) === true) { 

header('Location: ../index.php'); 

} 
else 
{ 

// Login form 

} 

Ganz gleich, abgesehen von den Dateiquellen als Admin login.php in /admin befindet. Trotzdem zeigt die erste das Login-Formular korrekt an, während die zweite Sie auf index.php umleitet (auch wenn inkognito, ein Mysterium für mich), eine Umleitungsschleife verursacht (wie index.php sendet es zurück für Nog angemeldet ist).

Darüber hinaus, wenn ich mich mit den richtigen Anmeldeinformationen anmelden, leitet es mich an index.php nur um mich zurück zu login.php mit Fehlercode 6 zu leiten.

Bitte Kommentar, wenn Sie weitere Informationen oder Codebeispiele wünschen, fühle ich mich verloren in meinem eigenen Projekt jetzt.

Jede Hilfe ist willkommen, Sie

UPDATE 17. Dezember danken:

Nach ein paar Stunden von Debug, haben wir festgestellt, dass das Problem nicht mit dem Code ist aber mit der Serverkonfiguration . Ein einfaches Beispiel:

<?php 

session_start(); 
echo session_id(); 

?> 

Wenn Sie diese Datei auf dem Produktionsserver öffnen und die Seite aktualisieren, zeigt es eine neue Session-ID mit jeder Anfrage. Ich habe derzeit keine Ahnung warum. Ich habe bestätigt, dass die Sitzungsdatei sowie das Cookie erstellt wurde. Es enthält die richtigen Informationen und kann von SSH mit Serverberechtigungen zugegriffen werden. Wirklich ein seltsames Verhalten.

Irgendwelche Hinweise?

+0

sicherstellen, dass die Sitzung nur einmal pro Anfrage gestartet wird, z. B. wenn mehrere Dateien 'sec_session_start()' in derselben Anfrage aufrufen, was wird passieren? –

+0

verschiedene Serverkonfigurationen behandeln Sitzungen unterschiedlich, zB über Cookies oder Dateien etc .. Die Art und Weise, wie die Sitzung initialisiert wird, macht einen Unterschied, dies sind nur allgemeine Kommentare –

+0

1) Haben Sie eine lokale 'php.ini' auf Ihrer verschiedene Server? Einstellungen wie "session.savepath" mit kontospezifischen Adressen, die sich auf Ihren Test- und Produktionsservern ändern. 2) Sind auf Ihren beiden Servern die gleiche PHP-Version installiert? 3) Führen Sie "phpinfo" aus und vergleichen Sie die Ausgabeeinstellungen auf den beiden Servern, um Unterschiede zu vergleichen (z. B. sitzungsbezogene Adressen). Gibt Ihnen irgendwas davon irgendwelche neugierigen Antworten? – Martin

Antwort

4

Überprüfen Sie, ob die Sitzung bereits begonnen hat und sicherzustellen, dass es nur einmal:

Mit PHP> = 5.4:

function sec_session_start() { 
    if (session_status() == PHP_SESSION_NONE) { 
     $session_name = 'login'; 
     $secure = false; 
     $httponly = true; 

     ini_set('session.use_only_cookies', 1); 
     session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); 
     session_name($session_name); 
     session_start(); 
     session_regenerate_id(); 
    } 
} 

Vor PHP 5.4:

function sec_session_start() { 
    if (session_id() == '') { 
     $session_name = 'login'; 
     $secure = false; 
     $httponly = true; 

     ini_set('session.use_only_cookies', 1); 
     session_set_cookie_params(86400, '/', '.domain.com', $secure, $httponly); 
     session_name($session_name); 
     session_start(); 
     session_regenerate_id(); 
    } 
} 

Zusätzlich warum die Sitzung haben regeneriert jedes Mal werden?

+0

Ich werde dies versuchen, aber beide Server sind auf dem neuesten Stand und sollten in diesem Fall nicht abweichen. In Bezug auf die Regeneration: Es ist derzeit auf jede Anfrage, da es der einfache Weg ist, um es zu sichern. Davon abgesehen könnte es auf nicht jede neue Anfrage reduziert werden. Ich glaube nicht, dass die Anzahl der Anfragen hier das Problem ist, und in den vorherigen Fällen habe ich den Code noch nicht verwendet. – Fredrik

+0

Das in der Tat nicht das Problem zu lösen :( – Fredrik

5

Ich habe Ihren Code durchgegangen und ich habe nichts ungewöhnliches außer nur 1 Sache gefunden.

Sie sollten niemals == für den Vergleich von Zeichenfolgen verwenden === ist in Ordnung.

$something = 0; 
echo ('password123' == $something) ? 'true' : 'false'; 

Führen Sie den oben genannten Code und Sie finden den Grund für Ihre Sitzung verloren. In Ihrer Funktion login_check verwenden Sie == für den Vergleich zweier String

if($login_check == $login_string) 

ersetzen Sie es mit:

if($login_check === $login_string) 

Else alles absolut in Ordnung ist. Wenn das Ändern dieses kleinen Dinges Ihr Problem nicht löst, lassen Sie es mich wissen.

Hinweis

Sie verbinden sich vor dem Start der Sitzung mit der DB. Ich würde Ihnen empfehlen, Ihre Funktion zu importieren, dann Ihre Sitzung zu starten und dann eine Verbindung zu Ihrer Datenbank herzustellen.

include_once "../functions.php"; 
sec_session_start(); 
include_once "../db_connect.php"; 
+0

Ich werde dies versuchen, sobald ich kann, morgen. Wenn dies die Lösung ist, und es sehr gut sein könnte, wie kommt es anders zwischen zwei Domänen? – Fredrik

+0

Kein Glück Ich habe Angst – Fredrik

+0

Kannst du den Code über die Einstellung der Sitzung posten.Wie hier Dinge richtig sind, dann musst du die Sitzung falsch setzen – Vineet1982

0

Ich hatte ein ähnliches Problem vor einigen Monaten auf meinem Produktions-Server erfahren, wo Sitzungen wurden abgelaufen bekommen (wie in Ihrem Fall Sitzungen zwischen den Seiten verloren werden immer) und Anwender wurde immer aus meiner Webseite abrupt angemeldet. Nach einigen Tagen Debugging kam also alles auf diese drei Zeilen in php.ini Datei.

  • session.gc_divisor
  • session.gc_maxlifetime
  • session.gc_probability

Von the manual,

  • session.gc_probability in Verbindung mit session.gc_divisor wird verwendet, um die Wahrscheinlichkeit zu managen Die Routine gc (garbage collection) wird gestartet. Defaults zu 1.

  • session.gc_divisor gekoppelt mit session.gc_probability definiert die Wahrscheinlichkeit, dass die gc (garbage collection) Prozess auf jeder Sitzung Initialisierung gestartet wird. Die Wahrscheinlichkeit wird unter Verwendung von gc_probability/gc_divisor, z.B. 1/100 bedeutet, dass eine Wahrscheinlichkeit von 1% besteht, dass der GC-Prozess bei jeder Anforderung gestartet wird. session.gc_divisor Standardeinstellung 100.

  • session.gc_maxlifetime gibt die Anzahl der Sekunden, nach der Daten werden als ‚garbage‘ und möglicherweise gereinigt gesehen werden. Die Garbage Collection kann während des Starts der Sitzung erfolgen (abhängig von der Sitzung).gc_probability und session.gc_divisor).

Und das war meine ursprünglichen Sitzungskonfigurationen in php.ini Datei, die tatsächlich das gesamte Ärgernis in erster Linie geschaffen hatte,

session.gc_divisor 1000 1000 
session.gc_maxlifetime 1440 1440 
session.gc_probability 0 0 

Dies bedeutet also, die Garbage Collector mit einem beginnen Wahrscheinlichkeit von session.gc_probability dividiert durch session.gc_divisor. Und unter Verwendung der Standardwerte für diese Optionen (0 bzw. 1000) ist die Speicherbereinigungswahrscheinlichkeit = session.gc_probability/session.gc_divisor dh 0/1000 = 0%, was ich für falsch halte, plus session.gc_maxlifetime schien mir zu niedrig .

Also entschied ich mich Sitzungskonfigurationen in meinem php.ini Datei zu ändern und diese Werte enthalten,

session.gc_probability = 1 
session.gc_divisor = 1000 
session.gc_maxlifetime = 28800 

Und da dann fein es funktioniert. Also mein Vorschlag an Sie ist, überprüfen Sie diese drei Werte in Ihrem php.ini Datei und wenn nötig, ändern Sie sie nach Ihren Bedürfnissen.

+0

Dies hat leider nichts geändert. Ich habe meine Frage mit einer Entdeckung aktualisiert, die ich heute gemacht habe. – Fredrik

+0

bitten Sie um Entschuldigung .. !! –

0

ich hatte ähnliche Erfahrungen in der Vergangenheit, ich erinnere mich nicht genau, wie ich dieses Problem lösen, aber von dem, was ich erinnere mich, es zu Session-Cookies und variable Reihenfolge in PHP bezogen.

Look für diese Linie unten in der php.ini,

variables_order = "GPCS"

irgendwie, die Reihenfolge dieser Vars Änderung der PHP-Sitzung betroffen.

, wenn durch eine Änderung, wie ich, Sie nicht die Einstellung auf dem Server ändern können, können Sie auch das Session-Cookie mit regelmäßigen Cookie versuchen zu duplizieren, indem Sie diese:

session_start(); 
set_cookie(session_name(), session_id()); 

und eine andere Note, unterschiedliche Browser verhalten sich auch beim Session-Cookie unterschiedlich, zB: Safari. Auf Safari muss ich den Cookie unabhängig von der Reihenfolge der Reihenfolge kopieren.

hoffen, es hilft

0

ich auch diese Frage gestoßen, aber es war ssl Installation, die die Basisdatei Link mit https geändert und war Datei zu senden, ohne ssl Link. Auch die Sitzungsdauer kam mir in den Sinn. Ansonsten kann mein Hosting Provider dies erklären.

Verwandte Themen