【问题标题】:Close session and start a new one关闭会话并开始一个新会话
【发布时间】:2010-12-03 11:21:17
【问题描述】:

我正在我的 PHP 会话中测试安全检查的实现。我可以成功检测到会话是否从另一个 IP 地址启动,并且可以成功启动新会话。但是,旧会话中的数据会被复制到新会话中!如何在为其合法所有者保留先前会话数据的同时启动空白会话?

这是我迄今为止的代码,经过多次失败的尝试:

<?php

// Security check
if( isset($_SESSION['ip_address']) && $_SERVER['REMOTE_ADDR']!=$_SESSION['ip_address'] ){
    // Check failed: we'll start a brand new session
    session_regenerate_id(FALSE);
    $tmp = session_id();
    session_write_close();
    unset($_SESSION);
    session_id($tmp);
    session_start();
}

// First time here
if( !isset($_SESSION['ip_address']) ){
    $_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
    $_SESSION['start_date'] = new DateTime;
}

关于会话的官方文档非常混乱:(

更新:我发布了我通过反复试验获得的一些发现。他们似乎工作:

<?php

// Load the session that we will eventually discard
session_start();

// We can only generate a new ID from an open session
session_regenerate_id();

// We store the ID because it gets lost when closing the session
$tmp = session_id();

// Close session (doesn't destroy data: $_SESSION and file remains)
session_destroy();

// Set new ID for the next session
session_id($tmp);
unset($tmp);

// Start session (uses new ID, removes values from $_SESSION and loads the new ones if applicable)
session_start();

【问题讨论】:

标签: php session


【解决方案1】:

只需在session_regenerate_id 之后调用session_unset 即可重置当前会话的$_SESSION

if (isset($_SESSION['ip_address']) && $_SERVER['REMOTE_ADDR']!=$_SESSION['ip_address']) {
    // Check failed: we'll start a brand new session
    session_regenerate_id(FALSE);
    session_unset();
}

【讨论】:

  • 手册不鼓励这样做:如果使用 $_SESSION [...],使用 unset() 取消注册会话变量,即 unset ($_SESSION['varname'])我>
  • @Álvaro G. Vicario:它说“[...] 使用 unset() 取消注册 a 会话变量 [...]”和“不要取消设置整个 $_SESSION unset($_SESSION) […]”。没有什么像*‍不要使用session_unset重置整个$_SESSION‍*‍‍。
  • 刚刚测试: session_unset() 删除会话数据。我不能在第一个会话中使用它,因为我想保留它,但我想我可以在第二个会话中使用它。听起来不合逻辑,但应该可以。
  • @Álvaro G. Vicario: session_regenerate_id 基本上是创建一个新会话并将会话数据从旧会话复制到新会话。所以调用session_unset 只会影响新会话,不会影响旧会话。
  • 在这段代码之后,您仍然需要调用session_start() 来开始一个新会话,对吧?还是真的重置了?
【解决方案2】:

当新用户连接到您的服务器时,脚本应该只能访问该用户的会话变量。您将希望将其他信息存储在散列会话变量中,以验证会话没有被劫持。如果它被劫持,没有理由开始一个新的会话,也许只是退出脚本并发出警告。

这是很多人用来对会话进行指纹识别的功能:

function fingerprint() {
    $fingerprint = $server_secure_word;
    $fingerprint .= $_SERVER['HTTP_USER_AGENT'];
    $blocks = explode('.', $_SERVER['REMOTE_ADDR']);
    for ($i=0; $i<$ip_blocks; $i++) {
        $fingerprint .= $blocks[$i] . '.';
    }
    return md5($fingerprint);
}

【讨论】:

  • 我不想因为用户的 ISP 或 DHCP 服务器更改了他的 IP 地址而对用户无礼 ;-)
【解决方案3】:

使用这个

unset($_SESSION['ip_address'])

而不是“未设置($_session)” 你也可以使用 session_destroy。

【讨论】:

    【解决方案4】:

    session_destroy 销毁会话数据。例如,

    session_start();
    $_SESSION["test"] = "test";
    session_write_close();
    session_start();
    // now session is write to the session file
    // call session_destroy() will destroy all session data in the file.
    session_destroy();
    // However the you can still access to $_SESSION here
    print_r($_SESSION);
    // But once you start the session again
    session_start();
    // all session data is gone as the session file is now empty
    print_r($_SESSION);
    

    会输出

    array([test] => "test")array()
    

    【讨论】:

    • 我已经好几年没研究这个问题了,但如果我没记错的话,session_destroy() 的问题是它不会删除文件(即,您仍然可以打开旧会话旧身份证)。我可能会再次测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多