Reputation: 3393
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;
}
}
}
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
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
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:
www
subdomain and not ALL subdomains.session_name()
for one of the domains. This was what I did.Upvotes: 1
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