2013-01-15 175 views
3

我有困難的時候用PHP做的事情一些很基本的會話安全類型:PHP會話再生安全

  • 應該從一個未經身份驗證的上下文切換到身份驗證時,會產生一個新的會話ID一個
  • 應該來自經過認證的上下文切換到無認證的一個

我想怎麼辦切換上下文時不僅再生會話ID,還時立即產生一個新的會話ID把東西放進去會話(如FLASH)切換這些上下文時。這三個頁面應該有希望澄清我的期望:

<?php 
/* page1.php */ 
session_start(); 
# Just putting something in the session which I expect to 
# not show up later 
$_SESSION['INFO1'] = 'INFO1'; 
?> 
<html> 
<a href="page2.php">Page 2</a> 
<?php print_r($_SESSION) ?> 
</html> 

所以在此頁顯示的時候,我希望看到INFO1顯示出來。我也期待當我回到這裏不看INFO2顯示出來。如果我還沒有會話ID,我希望得到一個(我這樣做)。

<?php 
# page2.php 
session_destroy(); 
session_regenerate_id(TRUE); 
$_SESSION['INFO2'] = 'From page 2'; 
session_write_close(); 
header('Location: page3.php'); 
exit; 
?> 

這將是最類似於一個註銷功能 - 我們通過傳遞TRUEsession_regenerate_id現有會話無效。另外,我把在(大概)會話的東西 - 這可能是像FLASH - 說:「你已經成功退出

#page3.php 
<html> 
<body> 
<?php session_start(); ?> 
<?php print_r($_SESSION); ?> 
</body> 
</html> 

在這個頁面上,我期待 2事情發生:

  • page2.php重定向應該給我一個新的會話ID的Cookie(它沒有)
  • 我期望爲print_rINFO2打印信息,和不是INFO1。它沒有來自INFO1的信息,但不包括來自INFO2的信息。

我與session_regenerate_id和重定向有非常非常不一致的結果。看起來像是用手工發送這個Set-Cookie頭文件 - 但即使我沒有,session_regenerate_id(TRUE)也會使舊會話ID無效 - 所以即使瀏覽器因爲某種原因沒有得到新的會話ID,因爲舊會話已失效,因此不會在會話中看到任何信息。

有沒有人有過這類問題的經驗?有沒有解決這些問題的好方法?

回答

4

基於documentation對於session_regenerate_id,聽起來像會話的內容始終保留。你傳遞一個TRUE參數,但只會刪除磁盤上的實際會話文件;存儲在其中的值保存在$_SESSION中,然後寫入新會話。

因此,也許手動消滅它:

$_SESSION = array(); 

不知道爲什麼你沒有看到新的cookie,雖然。你在哪裏檢查,你看到了什麼?

編輯:OP下面評論中顯示的問題似乎是第2頁從未調用session_start加載第一個會話。其中產生以下內容:

<?php 
    session_start(); # Load the old session 
    session_destroy(); # Nuke it 
    session_unset(); # Delete its contents 
    session_start(); # Create a new session 
    session_regenerate_id(TRUE); # Ensure it has a new id 
    $_SESSION['FLASH'] = "You've been logged out"; 
    session_write_close(); # Convince it to write 
    header('Location: index.php'); 
?> 

我不知道這是否最小化。弄清楚它可以刪除多少可作爲練習讀者。

+0

呃 - 正確 - 在'page2'中加入'session_destroy'清除會話內容,但新內容仍然沒有添加,並且新的會話ID不會被髮送。 我查看是否通過查看兩個webkit工具來查看當前的網站cookie是否發送了新的會話ID。因爲我不能相信它沒有發送一個新的cookie,所以我也檢查了一個MITM代理 - 它絕對不會發送一個新的cookie。 – Colselaw

+0

此外,更新原始帖子以反映該建議。 – Colselaw

+0

'session_destroy' _also_僅影響磁盤上的文件。它不會擦除'$ _SESSION'。通過創建一個新的會話,您可以在PHP的某個位置存儲第一個會話剩下的所有會話數據。嘗試在第2頁的每行後面添加'$ _SESSION',你應該看到發生了這種情況。 – Eevee