2013-01-15 54 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