2014-09-23 10 views
5

Ho un problema con alcune funzionalità sessione e il modo in cui Chrome fa prefetching/rendering. Sto tentando di interfacciare un pezzo di software del forum (esoTalk) con un'app personalizzata di laravel 4.3. Ho ascoltatori di eventi di autenticazione che fanno sì che laravel crei una sessione php (in aggiunta alla sessione integrata in laravel) che consente al forum e all'app di condividere i dettagli di autenticazione. All'accesso al forum e se l'utente non ha effettuato l'accesso, ma queste informazioni condivise esistono (ovvero l'utente ha effettuato l'accesso sull'app di laravel), il forum accederà a quell'utente utilizzando le informazioni disponibili nella sessione.Problema con session_regenerate_id e Chrome prefetch/render

Per la maggior parte questo funziona bene, tranne Chromes prefetching sembra essere rompere le cose. Se controllo il forum usando un debugger, posso vedere che quando scrivo l'url del forum, ma prima di premere invio, chrome accederà al forum. Seguendo con il debugger posso vedere che fa tutto ciò che deve fare ed è riuscito ad accedere. Come fase finale il forum rigenera l'id della sessione per fermare il dirottamento. Questo è dove si rompe. Sembra che Chrome ignori il nuovo ID di sessione (inviato tramite un'intestazione di SetCookie http) in modo che quando prendo Invio, vado al forum (e faccio una richiesta completamente nuova) usando l'ID di sessione originale. Questo ID non esiste, quindi vengo impostato con uno nuovo e di conseguenza perdo lo stato di accesso. Per l'utente questo sembra proprio come non hanno mai avuto registrati.

Googled alta e bassa per suggerimenti su come posso risolvere questo. Sono riluttante a rimuovere la rigenerazione dell'ID di sessione in quanto serve a scopi di sicurezza. Inoltre non posso disabilitare il chrome prefetching/rendering. Tutto sommato mi sembra di essere un po 'sottaceto.

Ho creato un codice che lo replica. Anche se si basa sulla pre-rendering calci in (quindi avrete bisogno di colpire ciascuno dei file tramite la barra degli indirizzi di un certo numero di volte) test1.php

// test1.php 

<?php 

function regenerateToken() 
{ 
    session_regenerate_id(true); 
    $_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13); 
    $_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]); 
} 

// Start a session. 
session_set_cookie_params(0, '/'); 
session_name("SessionBork_Test_session"); 
session_start(); 

$_SESSION["SentryUserId"] = '99'; 

regenerateToken(); 

header('Content-Type: text/plain'); 
foreach ($_SESSION as $k => $v) { 
    echo $k . " = " . $v . "\n"; 
} 

accesso seguito da test2.php e si dovrebbe vedere un mazzo di output di variabili di sessione. Non appena si prerenderanno/recupereranno i calci, inizierai a ricevere un messaggio interrotto.

// test2.php 
<?php 

function regenerateToken() 
{ 
    session_regenerate_id(true); 
    $_SESSION["token"] = substr(md5(uniqid(rand())), 0, 13); 
    $_SESSION["userAgent"] = md5($_SERVER["HTTP_USER_AGENT"]); 
} 

// Start a session. 
session_set_cookie_params(0, '/'); 
session_name("SessionBork_Test_session"); 
session_start(); 

if (empty($_SESSION["token"])) regenerateToken(); 

// Complicate session highjacking - check the current user agent against the one that initiated the session. 
if (md5($_SERVER["HTTP_USER_AGENT"]) != $_SESSION["userAgent"]) 
    session_destroy(); 

// Log in a the user based on the SentryUserId 
// ... logging in, setting userId, regenerating session 
$_SESSION["userId"] = '10'; 
regenerateToken(); 

header('Content-Type: text/plain'); 
foreach ($_SESSION as $k => $v) { 
    echo $k . " = " . $v . "\n"; 
} 
if (! isset($_SESSION['SentryUserId'])) echo "\n--\nPrerendering brokeded me."; 

Se si può ottenere collegato a Xdebug in un IDE o qualcosa che dovrebbe vedere la PreRender nascosta colpito a test2.php (che sembra essere assolutamente corretto nella risposta) e poi il successivo colpo vero e proprio quando premi Invio dove è dimenticato chi sei.

+0

Ho trovato un vecchio problema di cromo che si riferisce a questo: https://code.google.com/p/chromium/issues/detail?id=86175 –

+0

Cosa succede quando si aggiunge session_write_close(); alla fine della funzione regenerateToken()? – twicejr

risposta

1

Un modo per aggirare questo problema sarebbe quello di rilevare pre-fetch, e non generare un nuovo ID di sessione su quei carichi. Vedere questo Stack Overflow per informazioni sul rilevamento prefetching in vari browser: HTTP header to detect a preload request by Google Chrome

Inoltre, direi che ci sono modi migliori per andare circa la prevenzione di dirottamento di sessione (ad esempio legando la sessione a un indirizzo IP, la firma del browser, ecc)

Inoltre, potrebbe esserci un secondo bug nel codice: chiamare session_destroy() distrugge la sessione E chiude la sessione dell'utente. È necessario chiamare session_start() prima di chiamare session_regenerate_id(). Vedere la documentazione here e gli esempi here.

Problemi correlati