Yusaf Khaliq
Yusaf Khaliq

Reputation: 3393

Can't store session data after session_regenerate_id();

I have a webpage where I would like to regenerate the session id when the user logs in. The issue I am having is I run session_regenerate_id(); and then try attaching $_SESSION['user'] = $row; where $row is an array.

I have tried everything in the book, for e.g destroying session and then starting again. I have been working on it for at least 2 hours and I have no solution.

I have removed a lot of irrelevant php and left some in so you get the gist of what I am trying to do but here's the script

<?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;
            }
        }
    }       

I have also tried with no luck.

<?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;
            }
        }
    }   

EDIT

Sorry I didn't clarify the title but basically I'll try storing the current session in a variable and I'll regenerate the session id and add try adding the stored session variable into the new session, however the session id does not contain the old data, and I am not getting any errors.

Upvotes: 7

Views: 1763

Answers (3)

junkfoodjunkie
junkfoodjunkie

Reputation: 3178

Correct me if I'm wrong, but why are you reassigning the content of $_SESSION? session_regenerate_id() doesn't null out the content of session, it just gives the session a new ID - the content of the session is still the same as before the regeneration. So there is no need to reassign values.

Hence, it should be perfectly valid to do this:

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

No need to reasssign.

Also, you should always check to see if a session is already started before starting the session, so do this at the beginning: if (session_id()) { session_start(); } instead of just session_start().

Upvotes: 0

Mike
Mike

Reputation: 24383

I had the very same problem once, but this really is just a shot in the dark because it was such a specific case.

I had two domains, www.domain.com and secure.domain.com. When I went to www.domain.com it set a cookie, however in the cookie params I set the domain to .domain.com, which means that it was used for domain.com and all sub-domains.

Then on secure.domain.com, I also used session cookies, however the domain used in the cookie was secure.domain.com (i.e. it would only work on the secure subdomain). to check if the user was logged in, I did something along the lines of if (isset($_SESSION['username'])) to check if it was set in the session, but since domain.com didn't use the array key username in its sessions, it was receiving the session cookie domain.com without that. Then when I logged in, I would set the username and all worked perfectly fine, up until the point when I regenerated the session ID. As soon as I did this, the user was immediately logged out again. It really took me a long time to figure out what was happening, but basically I was left with two session cookies on the browser, one that was sent to .domain.com and the other sent to secure.domain.com and they were conflicting with each other.

This can be fixed in two ways:

  1. make the cookie from the main domain only be for the www subdomain and not ALL subdomains.
  2. Use a different session_name() for one of the domains. This was what I did.

Upvotes: 1

Andrei B
Andrei B

Reputation: 2770

Are you sure that $login_ok gets set to true? You could print something there to be sure. From my test (simplified version of your script), it seem to work ok:

<?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>";  

Upvotes: 0

Related Questions