What things should be saved in SESSION and what should not be? - php

I give one example why this question appears in my head:
Lets say i create class 'PDOstart' which extends PDO class. On class 'PDOstart' all variables needed for PDO is defined on private section (like host, user, password and ect). So it makes very easy to use PDO class like:
$con = new PDOstart();
$con->query("SELECT ... ");
Because on my webpage I use only one DB I begin thinking why not add PDOstart object into SESSION? like: $_SESSION['db'] = $con; ? So i don't need on every page do "new PODstart". But I'm not sure that will be good idea...
Is there anything what i should avoid add to $_SESSION (for security or performance reason)?

user id so that every time the page loads you know what use is browsing, meta data such as timespan from page changes (Bot Detect), Local information, User template selection. anything that's required for that session really.
As you stated $con let me explain something.
There are several variable types in php and the main ones are:
strings
boolean's
integer's
objects
arrays
resources
Now you can store all of them into the sessions apart from resources, as there such things as file handles, connections to external entities there only open for the time it takes the page to be processed by PHP, then there closed.
the others are ok as there stored in the memory and are static as such, they will not change unless you programmatically change them.
The main entites you should store in the session are
GUID: So that you can track what user is logged in.
Flash Data: So if your doing a redirect you will be able to show a error message on the other page.
Browser Data, so that you can compare that the browser that is currently browsing is the same as the last, this way you can kill the session fro security.
Things like Database Data such as User Rows should not be stored in the session and you should create a separate cache mechanism to do this for you.

You can store your PDOstart class in the session, as long as you keep this in mind:
When you do $_SESSION['key'] = $obj, you actually serialize the object (assuming default php session handler, that happens when the data is flushed).
When you do this to a 'resource', such as a database connection, there is every likelihood the connection will not persist.
To workaround such cases, php has the __sleep and __wakeup magic methods
I would assume your PDOstart class will ensure connection to PDO on both __construct and __wakeup, doubling the complexity.
However, there's another reason for not doing it that way: the session might go away at any moment, so you shouldn't really rely on any information being there. Surely you can place safeguards, which would re-initialize everything, but that again is adding unneeded complexity.
There's no golden rule (at least that I'm aware of) that explicitly states you should keep as little info as possible in your sessions, but it seems to be a fairly common approach. I'd keep a user id and probably an access token. There's not much stopping you to do it otherwise tho.
As for security, this kind of use shouldn't really matter, as long as the session as a whole is secure. They never truly are, but it's a whole different topic.
Short answer: good things to store - user id, bad things to store - everything else.

Some complement to the good response of RobertPitt you should really add an autoloader if you start storing objects in the session.If the class of your object is not available you'll get a standard broken objet if you do not have an autoload mecanism for class loading.
Then, depending on how your session are stored you should be careful of the size they take. let's say you store it on a very fast drive or on a memcached service, you do not need to worry too much about the fact that this file will be read for every request of your user. If you have slow IO on your drive be careful. Now if you store your session in a database you may care about the insert/update/delete rythm on the session table, some databases (think about MySQL) are not very god at handling an high write load on one table.
In term of security you do not have to worry too much about session storage as it is on the server. At least if you (the admin) use disk storage you should ensure that all handled application are not using the same directory for session storage, if not the weaker application will define you security level for sessions.

Related

Is PHP session still used nowadays?

Is there a more contemporary alternative to PHP session or is PHP session still the main choice to store information? I read this: https://pasztor.at/blog/stop-using-php-sessions. I'm still learning PHP and frankly, I'm quite clueless.
Your first assumption is incorrect. PHP Sessions are not where you store data. Databases, files, Document stores, etc. are where you store your data.
Session "data" is simply the variables included in the $_SESSION array in serialized form. You can run serialize() and unserialize() on variables to gain some insight into what these look like.
In your script, once you have started a session using session_start(), when you add change or delete variables in $_SESSION, php serializes this and stores it for you.
Once a session exists, and a user makes another request that is identified as being the same user (having the same session id) which has typically passed to the client via a cookie, then upon issuing session_start(), PHP reads the serialized data in the session file, and unserializes it, and stores it back into $_SESSION.
By default, PHP will store the individual session data as files on the filesystem. For a small or medium size application, this is highly performant.
So to be clear, what people store in PHP sessions is basically variables read out of whatever other persistent storage you might have, so that you can avoid doing things like re-querying a database to get the name and user_id for a user who has already logged into your application.
It is not the master version of that data, nor the place through which you will update that data should it change. That will be the original database or mongodb collection.
The article you posted has a number of stated and unstated assumptions including:
Devops/Sysadmins just decide to reconfigure PHP applications to change the session handlers (misleading/false)
The deployment involves a load balancer (possibly)
The load balancer doesn't support or use sticky sessions
He then goes on into some detail as to several alternatives that allow for shared session handlers to solve the race conditions he describes
As you stated, you aren't clear yet what sessions actually are, or how they work or what they do for you. The important thing to know about PHP scripts is that they are tied to a single request and sessions are a way of not repeating expensive database reads. It's essentially variable cache for PHP to use (or not) when it suits your design.
At the point you have a cluster, as pointed out in the article people often store data into shared resources which can be a relational database, or any of many other backends which each have different properties that match their goals.
Again, in order to change the session handlers, there is typically code changes being made to implement the session handler functions required, and there are ways to code things that mitigate the issues brought up in the article you posted, for just about every persistence product that people use.
Last but not least, the problems described exist to whatever degree with pretty much any clustered serverside process and are not unique to PHP or its session mechanism.
Usually, that will depends on the use case and other requirements of your application and most of the time people will use PHP frameworks to handle sessions.
Take for example, for Yii 2 framework, the framework provides different session classes for implementing the different types of session storage. Take a look at here https://www.yiiframework.com/doc/guide/2.0/en/runtime-sessions-cookies.
Learning the different types of sessions available out there, allows you to be able to make decisions by weighing the pros and cons. You can also read here for more understanding https://www.phparch.com/2018/01/php-sessions-in-depth/

Storing data into session and storing to database upon "major" action

I know there are hundreds of these questions but what I am asking however is slightly different.
When the user logs in I would like to get all their data from each table in a database and store it in a session variable (obviously not sensative data such as encrypted password/salts etc basically data that would be useless or have no value to a hacker!!), and whilst the user uses the website the relevant data stored in the session will be used as opposed to accessing the database everytime. Moreover when the data is changed or added this will be written or added to the session file, and upon a major action such as "saving" or "loggin out" the new/changed data will be written to the database.
The reason I wish to do this is simply for efficieny, I want my application to not only be fast but less resource consuming. I am no expert on either which may explain why my idea makes no differnece or is more resource intensive.
If there is an alternative to my solution please let me know or if there is something to improve on my solution I will be glad to hear it.
Thank you.
My application is using PHP and mysql.
If any of these don't apply to your app, then please ignore. In general, I'm against using sessions as caches (especially if anything in the session is going to be written back to the DB). Here's why.
Editing the session requires a request from the user. Editing a php session outside of the request-response cycle is very difficult. So if a user Alice makes a change which affects Bob, you have no way to dirty Bob's cache
You can't assume users will log out. They may just leave so you have to deal with saving info if the session times out. Again, this is difficult outside of the request-response cycle and you can't exactly leave session files lying around forever until the user comes back (php will gc them by default)
If the user requires authentication, you're storing private information in the session. Some users may not be happy about that. More importantly, a hacker could imploy that private information to conduct a social engineering attack against the end-user.
Mallory (a hacker) might not be able to use the information you put in the session, but she can poison it (ie. cache poisoning), thereby causing all sorts of problems when you write your cache to your permanent storage. Sessions are easier to poison then something like redis or memcache.
TL;DR Lots of considerations when using a session cache. My recommendation is redis/memcache.
You can also go for local-storage in HTML5, check The Guide and THE PAST, PRESENT & FUTURE OF LOCAL STORAGE FOR WEB APPLICATIONS
Local Storage in HTML5 actually uses your browsers sqlite database that works as cookies but it stores data permanently to your browser
unless someone by force remove the data from the browser finding the data files
Or if someone remove/uninstall browser completely,
or if someone uses the application in private/incognito mode of the browser,
What you need to do
Copy the schema for required tables and for required columns and update data at a regular interval
you dont have to worry about user's state, you only have to update the complete data from the localStorage to mysql Server (and from the mysql server to localStorage if required) every time user backs to your application and keep updating the data at regular interval
Now this is turning out to be more of localStorage but I think this is one of the best solution available for me.
redis is a good solution if it is available for you (sometimes developers can't install external modules for some reason) what I would do is either go with your Session approach but with encoded/encrypted and serialized data. Or, which I really prefer is to use HTML5 data properties such as:
<someElement id="someId" data-x="HiX" data-y="Hi-Y" />
which BTW works fine with all browsers even with IE6 but with some tweaks, specially if your application uses jquery and ajax. this would really be handful.
You need to use Memcache for this kind of work. To solve the problem of keeping the updated data everywhere you can create functions for fetching the data, for example when the user logs in you, authenticate the user and after that insert all the user data into the memcache with unique keys like :-
USER_ID_USERNAME for user's username
USER_ID_NAME for user's name
etc...
Now create some more functions to fetch all this data whenever you need it. For ex
function getName($user_id){
if(Memcache::get($user_id."_name"){
return Memcache::get($user_id."_name");
} else {
//Call another function which will fetch the data from the DB and store it in the cache
}
}
You will need to create functions to fetch every kind of data related to the user. And as you said you want to update this data on some major event. You can try updating the data using CRON or something like that, because as tazer84 mentioned users may never log out.
I also use what the OP described to avoid calls to db. For example, when a user logs-in, i have a "welcome-tip" on their control panel like
Welcome, <USERS NAME HERE>
If i stored only his user_id on $_SESSION then in every pageview i would have to retrieve his information from the database just to have his name available, like SELECT user_name FROM users WHERE user_id = $_SESSION['user']['user_id'] So to avoid this, i store some of his information in $_SESSION.
Be careful! When there is a change on data, you must modify the data in db and if successfull also modify the $_SESSION.
In my example, when a user edits his name (which i also store in $_SESSION so i can use it to welcome-tip), i do something like:
If (UpdateCurrentUserData($new_data)) // this is the function that modifies the db
{
$_SESSION['user']['user_name']=$new_data['user_name']; // update session also!
}
Attention to:
session.gc_maxlifetime in your php.ini
This value says how much time the $_SESSION is protected from being erased by the garbage collector (the file that exists on your disk in which the $_SESSION data are stored)
If you set this very low, users may start getting logged-out unexpectedly if they are idle more than this amount of time because garbage collector will delete their session file too quickly
if you set this very high, you may end up with lots of unused $_SESSION files of users that have left your website a long time ago.
also i must add that gc_maxlifetime works together with session.gc_probability where in general you need lower probability for high-traffic websites and bigger probability for lower traffic since for each pageview there is a session.gc_probability that garbage collector will be activated.
A nice more detailed explanation here http://www.appnovation.com/blog/session-garbage-collection-php
I know this sounds stupid but ....
If ur data is not sensitive the best way to make it accessible faster is to store it in hidden variables inside the forms itself. You can save comma separated or values in an array.

Is it a good practice to save an object in a session?

I'm developing a generic app on PHP that is dynamically customized for many clients.
I have the class client, where I load the style and preferences for the client.
My question is:
Is it a good practice to save that object in a session? (I think that is the best solution instead of creating the object in each page, that will need lots of mysql querys.
There are few things you need to consider while you deal with session.
You should not store vary large values in session.
i think this is not a problem in your case as preferences are usally small enough.
When you store object in session. you might not get realtime updates. as for example lets say same user is logged in using two separate browsers and/or machines and modify preferences in one. in this case other one will not have the updated customization. its not a big problem but depends on your requirements.
I don't see any other problem here. in fact its valid and good solution to store small values in session and avoid db queries.
if it's something that won't change, and will just result in constantly calling MySQL queries over and over then yes, that is a good idea.
MySQL queries (and functions in general) are memory/cpu intensive and can affect page load speeds for the PHP, so the less work you are causing it to do the better.
if the returned values are going to be changing constantly it would be better not to, but store what values you can in the session.
I think the session will die when client close the browser.
If you store it in cookie (Loaded client) ? it not good for security.
When you store mini data in session (Loaded server).that mean you are using some memory at server.
What happen at the time you have many client ?
So, the database connection should be destroy at the end of process for each page.
Don't worry to use it.

How does PHP track created objects?

This may be a bit of daft question, but I don't come from an OOP background and although I'm reading and learning as I go I'm still struggling with a few concepts.
Right now I'm working with PHP 5.3 and desiging a fairly simple login using a few different object classes: User which defines the user. Session which starts and maintains session data and if someone is logged in, and Database which does the queries.
So when my script is run, my session object is instantiated, etc... here's my problem though. When I move from one page to the next how is that object tracked? Or perhaps rather my question is how does PHP know the objects that relate to my login are mine and not someone else who logged into the site?
I know if I'm doing this in a non OOP way, I'd simply check the session cookie on each page and check my data that way, which is fine my brain can handle that. But, where and how is object data tracked.
EG:
On each page I want to check if someone is logged in I reference $session->is_logged_in() etc is_logged_in checks the a private variable name is true or false.
There's no checking of cookies at this point which means this object still exists, and, as it keeps asking for a stored variable the instance must persist to be useful... but how does PHP, the server, whatever tie that instance of that object to that user? If all of these objects float around on the server till I destroy them won't there be lots of memory used by objects?
As I said at the start it's probably a really basic, fundatmental question but I'm yet to have my eureka moment with this, I might go back to simpler PHP.
Session data (that is all the data in $_SESSION) is by default serialized and stored to file between requests. The data gets unserialized automatically when session_start() is called.
From the PHP manual on Session Handling (emphasis mine):
The session support allows you to register arbitrary numbers of variables to be preserved across requests. When a visitor accesses your site, PHP will check automatically (if session.auto_start is set to 1) or on your request (explicitly through session_start() or implicitly through session_register()) whether a specific session id has been sent with the request. If this is the case, the prior saved environment is recreated.
Nothing is persisted in memory between requests. PHP has a shared nothing architecture, meaning all objects are recreated on each request anew, unless you are using dedicated cache mechanisms.
So when my script is run, my session object is instantiated, etc... here's my problem
though. When I move from one page to the next how is that object tracked? Or perhaps rather
my question is how does PHP know the objects that relate to my login are mine and not
someone else who logged into the site?
When you start a session, an id is generated. All the session data is associated with that id and it is given to the browser to store in a cookie. Subsequent requests include that id in the cookie, and PHP pulls the data out from where it has stored it.
If all of these objects float around on the server till I destroy them won't there be lots of memory used by objects?
The objects are serialized to files rather than being held in RAM, and are cleaned up with the session expires.
I find that sometimes, when I start to lose perspective as to whats really "happening", a quick trip to a page with phpinfo();,or just logging some ENV variables often clears things up, and puts me back on track…
Globals let you see exactly what "exists" in your environment, and allow you to take a mental restocking of what you're "working with", and how to best attack the challenge.. You'll find a wealth of information, and as to your specific "issues" there are such entries as…
$_SERVER["HTTP_COOKIE"]
$_SERVER["QUERY_STRING"]
$_SERVER["argv | c"]
$include_path
etc…
also, it never hurts to read through your /etc/php.ini (wherever the case may be) for a little one-on-one-time with PHP's internals - to remind you "what its all about".

Best practice for storing global data in PHP?

I'm running a web application that allows a user to log in. The user can add/remove content to his/her 'library' which is displayed on a page called "library.php". Instead of querying the database for the contents of the users library everytime they load "library.php", I want to store it globally for PHP when the user logs in, so that the query is only run once. Is there a best practice for doing this? fx. storing their library in an array in a session?
Thanks for your time
If you store each user's library in a $_SESSION as an array, as you suggested (which is definitely possible) you will have to make sure that any updates the user makes to the library are instantly reflected to that session variable.
Honestly, unless there is some seriously heavy querying going on to fetch a library, or you have tons of traffic, I would just stick to 'execute query whenever the user hits library.php'.
Consider the size of the data. Multiply that by the maximum number of concurrent users.
Then compare that the to memory avaiable on your server. Also consider whether or not this is a shared server; other sites needs resources too.
Based on this, it is probably best to either create a file that can be used (as per Remi's comment), or remain in the default stateless form and read every time. I doubt that reading the data each time is creating much of an overhead.
When the user login you can generate a xml file (USER_ID.xml for instance) that you display with xslt.
http://php.net/manual/en/book.xslt.php
Each PHP script dies when it completes, so data can not be kept permanentely live in a web application as you would do in a PC application.
One way could be sessions, but it depends on the amount of data you want to save. According to your example you are talking about a library, so it sounds to me like big quantity of data need to be saved, in such case the DB is the way to go, and yes you have to query it each time.
Another way could be to save them in an array inside a php file, but in the same way you have to query the DB each time, you would have to include such php file each time.
Since this is a db performance optimization, I would suggest that you take a look at memcached which matches your problem perfectly:
memcached is [..] intended for use in speeding
up dynamic web applications by
alleviating database load.
I think it would be best to store it in a Session.
It the user logs in, the Session is being created and you can save data in it using the superglobal:
$_SESSION['key'] = "value";
You can also store Arrays or everything else there and it can be cleared if the user logs out.
you care for performance; Please note:
Session may use database or file to store data.
database is here to be used instead of files, for it's performance and abilities.
use database, it is designed to be used exactly in such situations!

Categories