session_regenerate_id()之后无法存储会话数据;

时间:2014-02-22 00:18:26

标签: php session

我有一个网页,我希望在用户登录时重新生成会话ID。我遇到的问题是我运行session_regenerate_id();然后尝试附加$_SESSION['user'] = $row;其中$ row是一个数组

我已经尝试了书中的所有内容,例如破坏会话然后重新开始。我一直在研究它至少2个小时,我没有解决方案。

我删除了很多不相关的php并留下了一些内容,所以你得到了我想要做的事情的要点,但这里是脚本

<?php
    session_start();
    if(!isset($_SESSION["CSRF"])){
        $_SESSION["CSRF"] = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);
    }
    if(!empty($_POST)){
        if($_POST["action"]==="login"){
            //querying DB for $_POST values
            $stmt = $db->prepare($query); 
            $result = $stmt->execute($query_params); 
            $login_ok = false;          
            $row = $stmt->fetch(); 
            if($row){ 
                $checked = //check password is okay
                if ($checked) {
                    $login_ok = true; 
                }
            }
            if($login_ok) { 
                session_regenerate_id();                
                unset($row['salt']); 
                unset($row['password']); 
                $_SESSION['user'] = $row;
            }
        }
    }       

我也试过没有运气。

<?php
    session_start();
    if(!isset($_SESSION["CSRF"])){
        $_SESSION["CSRF"] = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);
    }
    if(!empty($_POST)){
        if($_POST["action"]==="login"){

            //querying DB for $_POST values
            $stmt = $db->prepare($query); 
            $result = $stmt->execute($query_params); 
            $login_ok = false;          
            $row = $stmt->fetch(); 
            if($row){ 
                $checked = //check password is okay
                if ($checked) {
                    $login_ok = true; 
                }
            }
            if($login_ok) {                 
                unset($row['salt']); 
                unset($row['password']); 
                $_SESSION['user'] = $row;
                $arr = $_SESSION;               
                session_regenerate_id(true);
                $_SESSION = $arr;
            }
        }
    }   

修改

抱歉,我没有澄清标题,但基本上我会尝试将当前会话存储在一个变量中,我将重新生成会话ID并添加尝试将存储的会话变量添加到新会话中,但是会话ID确实不包含旧数据,我没有收到任何错误。

3 个答案:

答案 0 :(得分:1)

我曾经遇到过同样的问题,但这真的只是在黑暗中拍摄,因为它是如此具体的情况。

我有两个域名, www.domain.com secure.domain.com 。当我访问www.domain.com时,它设置了一个cookie,但是在cookie params我将域设置为.domain.com,这意味着它用于domain.com和所有子域。 / p>

然后在secure.domain.com上,我也使用了会话cookie,但cookie中使用的域名是secure.domain.com(即它只适用于secure子域名)。为了检查用户是否已登录,我在if (isset($_SESSION['username']))行做了一些事情来检查它是否在会话中设置,但是因为domain.com没有使用数组键username在其会话中,它没有收到会话cookie domain.com。然后当我登录时,我会设置username并且所有工作完全正常,直到我重新生成会话ID。一旦我这样做,用户立即再次注销。我花了很长时间才弄清楚发生了什么,但基本上我在浏览器上留下了两个会话cookie,一个发送到.domain.com而另一个发送给{ {1}}他们彼此冲突。

这可以通过两种方式解决:

  1. 使主域中的Cookie仅用于secure.domain.com子域,而不是所有子域。
  2. 为其中一个域使用不同的session_name()。这就是我所做的。

答案 1 :(得分:0)

你确定$ login_ok设置为true吗?你可以在那里打印一些东西。从我的测试(脚本的简化版本),它似乎工作正常:

<?php
session_start();
$data = $_SESSION['data'];
$sid = session_id();
echo "Old data is $data<br>Sid is $sid<br>";
if($_GET["action"]==="login"){
    session_regenerate_id();                
    $_SESSION['data'] = $data + 1;
}
$data = $_SESSION['data'];
$sid = session_id();
echo "New data is $data\n<br>Sid is $sid\n<br>";  

答案 2 :(得分:0)

如果我错了,请纠正我,但为什么要重新分配$ _SESSION的内容? session_regenerate_id()不会使会话内容为空,它只是为会话提供一个新ID - 会话内容仍然与重新生成之前相同。所以没有必要重新分配价值观。

因此,这样做应该是完全有效的:

if($login_ok) {                 
  unset($row['salt']); 
  unset($row['password']); 
  $_SESSION['user'] = $row;
  session_regenerate_id();
}

无需重新签名。

此外,在开始会话之前,您应该始终检查会话是否已经启动,所以在开始时执行此操作:if (session_id()) { session_start(); }而不仅仅是session_start()