PHP Session ID being regenerated automatically - php

I have found that on my simple web application, if you leave the page alone for more than about five minutes and then reload the page, calling session_id() will return a different value the second time. Users remain logged in, so the session data is being moved across to the new ID, but I keep track of cart items in a MySQL database based on the session ID, and when the ID changes, the association with the cart items is lost.
Nowhere in my code do I ever call session_regenerate_id()
Help!

You might want to check your code to see if you are using session_id() with an argument anywere as this will also change the session id. Without seeing the code it is hard to be specific as to a fix or to know what is going wrong.

Few more things you might want to check if encountered such situation AND you do use session_name():
From PHP Online Manuals:
Warning! The session name can't consist of digits only, at least one letter must be present.
Make sure you dont have spaces in your session_name() argument like
session_name('blah blah')
Both situations force a new session id generated every time.

Related

PHP - How to tell current session id to the next server request?

I'm having a big trouble here: In my company we have a huge system and too many people access it every day. We are having the following problem:
User access his account on the pc A.
He goes to write his text
He write all his text but doesn't save it. Then open a new tab.
In the new tab, he access the account of his customer.
Using the account of his customer, he goes to write the customer's text.
After type the customer's text, he goes to the previous tab to save his own text and after save the customer text.
The two texts appears on the customer's page.
I was thinking in a way of the current screen store somewhere the actual session id, and then when the user click in a link, or post a form, the current page send the session id loaded when it was rendered to the requested page.
Can you help me please?
Thanks!
Its a little difficult to follow the use case specified, but it sounds like you need to check access rights to save 'text' to a particular account.
at the moment it appears that your authenticated customer account is saving to an account that isnt theirs?
for eg, in the new text method, before anything happens:
if($currentUserID != $accountOwnerID)
{
// throw a 403 exception here
}
this way if they happen to change identity during a session, their access rights will always be checked before anything else can happen.
The best solution is to use named sessions. See: session_name()
By using it, you can have different (and isolated) sessions which will not conflict to each other, even if in the same computer, same browser.
For your particular case, I would create a session named after the user logon, which is unique. That way, if user A logs in, he will have his own session. If a new tab is opened, and he logs as user B, a different session will be created, and both tabs will work simultaneously and correctly, each on it's own session space.
Just add session_name($UserLogon); before session_start(), should work good.
You can use session keys to check.
For that first you need to create a random session key and store it in a session variable. Also provide this value as a hidden element in your form. During the insertion you can check whether the value in hidden element is same as the session key, then insert. Else through error message. After successful insertion reset the session key again. It will overcome your problem.
Hope it helps.

How can I make a username change and also update the session?

I've got my login sorted, which sets an array of around 15-20 different database items, the user can change some of these and admins can change all of them.
Obviously for a general user, it would be silly having to reset the entire session when they change something on their account. For example their name. My code DOES work with the database, it is inputting the name after the user changes it.
$username=$this->session->userdata("logged_in");
if(strlen($name)>=1){
$databasename = $row->firstname;
if($name != $databasename){
$input_array['first']= $name;
$this->session->unset_userdata($username['name']);
$this->session->set_userdata($username['name'],$name);
}
}
To add some background to my code, the input array is defined outside of the if statements, and is the added to if the name is NOT equal to the database name and if the name has been changed.
All it does, is save the data to the database, and does not change the session variables. Ideally they need to change, they do change if i log off then back on, however this is impractical.
If i understood your correctly, you want to make sure that the user always get's displayed the up to date data, even when the admin did some changes to it, e.g. to his username. If so, then there are 3 ways to do this.
The first one
Only store the userid in the session as well as any data that does not need to be up to date. You then select the needed data, e.g. the username from the database when a request has been made. That will ensure that everything is always up to date.
The second one
Store the userĀ“s session id in the database when it will be created. To get the session id use the session_id function. You then use the session_id function again, but this time with the id from the sesison you want to destroy as the first parameter. e.g
session_id($old_session_id);
session_start();
session_destroy();
This will crerate an empty session (and therefore kill the existing one), and destroy is right after that. and then the user has to log in again when he visits your site the next time.
The third one
Let PHP store the sessions in the database, that way you can modify them or simple remove them and force the user to relog. I would however be careful with this solution at it might be an overkill, the first one tho is a very common one, the second one is also a great way.
Explanation
The reason why it does not work otherwise, is the fact that the session does still contain the old data which has been set previously. If the user updates his username himself then you can also set it at the session, but if the admin does it (or any other one except for the user himself), the username (just as a example, it can of course be anything else) in the session won't change.
Maybe because you get variable $logged_in and try to put back another variable with name "username". If i right understand your problem you need save logged_in:
$username['name'] = $name;
$this->session->unset_userdata('logged_in');
$this->session->set_userdata('logged_in',$username);

Passing PHP Session ID as a POST parameter

In light of my recent issue (PHP - Session lost/emptied on form post), the session ID almost by random regenerates itself upon a form being posted (login -> add item to basket OR add item to basket -> login), resulting in the session data being lost. A work around was brought to light that I could pass the session ID as a hidden input to force the session ID to maintain itself. Is this a practical fix? And would this open me up to any vulnerabilities?
Please note that my website is run on a shared server.
It doesn't affect the level of your security. The session ID is stored as a cookie on the user's browser and you propose saving it in the HTML source. Either way, the end user or a malicious entity using a network sniffer will be able to access this data. So you can use it if it makes your job easier.
I'll take a stab in the dark and guess that when you're submitting the form to a different subdomain, i.e. you're on http://www.example.com, and you're submitting to https://secure.example.com or the like.
If so, you need to make sure that the session cookie domain is set to use all subdomains of your website, not just your current one. You can check that with:
ini_get('session.cookie_domain');
// if this outputs something like "www.example.com" and you're submitting to
// "somethingelse.example.com", here's your problem.
If it's not set properly, you can set it either in php.ini or in your scripts:
ini_set('session.cookie_domain', '.example.com'); // or...
session_set_cookie_params(ini_get('session.cookie_lifetime'), ini_get('session.cookie_path'), '.example.com');
session_start();
... alternatively, you can just make sure that you're using the same subdomain when you submit the form as there's rarely a good reason to use a different one in this context.
Or your problem could be completely unrelated. Worth checking out in any case.
But, as #Kaustubh Karkare said, the security of passing session variables through your form is identical to passing them through cookies. And as for practicality, it's a perfectly reasonable, if not often used, way to pass session ids around.
Instead of posting it, go to your action page from your form and use this
<?php
//let's start the session
session_start();
$_SESSION['whateveryouwanttocallit'] = session_id()
?>
So basically don't post it at all....
You can check it by the following:
<?php print_r($_SESSION)?>
And can confirm it to: <?php echo session_id()?>
In answer to your question however, this is not a good work around.
By posting a session id to your session, you're just creating a duplicate of the information and naming it whatever you want, the session ID is already in your session.
Also, if you're intending to use your session ID in a hidden input as a form of cookie to ensure they information on that user isn't lost, the problems will be:
The session with this newly created session id will also get wiped.
Even if it stayed, the session id will have been regenerated and so be a different string.

Shopping Cart/Login State - No Cookies?

No cookies at all. Is that possible? And how exactly?
The only thing I can think of is if you create a hidden button with an id when the user first accesses the site. That id can then be propagated from page to page. When something is added to a shopping cart, you use ajax to save that selection to the id.
Ye olde method was indeed propagating the token as a GET or POST variable throughout the process, which easily breaks (hence still the possibility in the session settings to enable it automatically with url_rewriter.tags ).
It can so easily break however, I don't think there's anything wrong with requiring people to enable cookies if they want to buy something from your site...
It doesn't need to be a hidden field, a URL parameter con serve. You keep an id generator and that id is passed as a parameter ?i=xxxxx on every URL. You then store stuff in the card associated to the id.
Session. They are no cookies. Notice they are named different...
I implemented this one in a breeze for a last project
https://github.com/Crinsane/LaravelShoppingcart
Sessions can track user until browser closed.

What is the best way to deal with sessions when the user may stay logged in, but a session key needs to be updated, because of another update?

I'm working a site where users could technically stay logged in forever, as long as they never close their browser (and therefore never get a new session key). Here's what I could see happening: a user leaves a browser open on computer A. The then use computer B, login and change their name which is stored in the session. They logout of B, but A is still logged in and still has their old name stored in the session. Therefore, their name won't be updated till the next time they logout manually or they close their browser and open it again and are logged in through the remember me function.
Name is a simple example, but in my case the subscription level of their account is stored in the session and can be changed.
How do you deal with this?
A few ideas that I have are:
After a period of 10 minutes or more, the session data get's reloaded. It might be exactly 10 minutes if the user is highly active as the function will get triggered right at the 10 minute point or it could be after 2 hours if the user leaves and comes back and then triggers the functionality.
Store as little information as possible in the session and load the rest from the DB on every page call. (I really don't like this idea.)
Use database sessions and use the same session on all the computers. I like this, but I could see it getting confusing when something like search criteria are stored in the session--the same criteria would show up on both browsers/comptuers.
For information, even such as the user's name or username/email address, store it in the session, but for other information that would heavily affect their abilities on the site, don't store it in the session and load when needed (attempt to only do it once per instance).
Are there other better methods?
--
Another option: 5. Use database session and when an update is made load the user's other sessions (just unserialize), change the relevant information and save them back to the database.
I would go either with number 1 or number 4. If you store the time of the last update of the information, you could even ask on every request whether the date has been updated.
Don't store information likely to change in the session, if you're looking at scenarios like the one you outline. Just get over your dislike of loading user data with every page - it's by far the best idea.
I'm guessing you don't want to load the data from the database because you're concerned about performance issues somehow. Before you try out any of the other solutions, you might want to test how long it takes to actually load a users data from the database, then check that against your number of users - chances are you won't see any performance problems due to loading user profiles on every page.
Regards
I'd go with option 6: only store userid and session specific stuff (search criteria) in his session and put the rest into APC/xcache (memcached if you're using multiple servers).
this way you'll only have to go to the database the first time (and after the cache expires) and you can still share any data between users sessions.
Normally you should do 2), but you don't like it.
maybe you can use sessions stored in db.
when a user change his name, put into all sessions from that user the information "refresh userdata".
on the next request the userdata is reloaded again into the session and is cached there.
this can be done be reusing your loaduserdata function which called at login.
php session_set_save_handler() - also read comments
php session_decode() - to read the username from the session to store it additionally to the sessiondata. usefull for easily to find the users sessions for updating.
[edit]
don't forget:
when you are updating all the sessions while the page is generated (between session_start and session_write_close) you changes maybe lost.

Categories