PHP会话再生安全性

时间:2013-01-15 01:18:07

标签: php security session

我在使用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;
?>

这最类似于注销功能 - 我们通过将TRUE传递给session_regenerate_id来使现有会话无效。此外,我在(可能)会话中添加了一些内容 - 可能就像FLASH一样 - 说“您已成功注销。

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

在这个页面上,我期待发生两件事:

  • page2.php的重定向应该向我发送一个新的会话ID cookie(它没有)
  • 我希望print_r打印来自INFO2的信息,来自INFO1。它没有来自INFO1的信息,但不包含来自INFO2的信息。

我与session_regenerate_id和重定向的结果非常非常不一致。手动发送Set-Cookie标题看起来像是一个kludge - 但即使我没有,session_regenerate_id(TRUE)无论如何都应该使旧的会话ID无效 - 所以即使浏览器由于某种原因没有得到新会话ID,它不会在会话中看到任何信息,因为旧会话已失效。

还有其他人有过这类问题的经验吗?有没有办法解决这些问题?

1 个答案:

答案 0 :(得分:4)

根据session_regenerate_id的{​​{3}},听起来总是会保留会话的内容。你传递了一个TRUE参数,但只删除磁盘上的实际会话文件;存储在其中的值保存在$_SESSION中,然后写入新会话。

所以也许可以手动擦除它:

$_SESSION = array();

不知道为什么你没有看到新的cookie。你在哪里检查,你看到了什么?

编辑:正如OP在下面的评论中所揭示的那样,问题似乎是page2从未调用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');
?>

我不知道这是否是最小的。弄清楚它有多少可以删除,留给读者练习。