I am building a website in which the user can select what list items they see in their navigation menu, my idea is to store the menu items that the user selects in a cookie as this will stop the need for the user to be registered member on the website, is it possible to store realtime data in a cookie and how would I do this? For more information the navigation options are built from a mysql result, the then clicks a link and that link is added to a different list, if they click it again it is deleted, I need to add/remove these items from the cookie as the user add/removes it from there list.
i would use the cookie only to identify the user and do all of your menu option saving in MySql.
Grab the user id from the cookie and query the db for the menu_options and display them.
Either way, storing the data in a cookie or in the database, when the cookie expires, so does (effectively) the user. Plus people delete cookies all the time using cleaners like Adware and CCleaner. I do this about once a week. Cookie = Gone.
This is a bad idea.
The number of cookies a browser can store is not defined (however there is a hard limit for most browsers). RFC 2109 suggests at least 20 cookies per host and a min cookie size of 4k. Certainly the latter is adhered to by most browsers.
You're also going to have to replicate all the features of session management without the nicety of having server-side state. You do not want the kind of pain going down this route will cause you. Keep your session data server-side.
There is no requirement for a user to 'log-in' to have a session. You just need to assign them an automatic identity in a persistent cookie (the replace that if they ever do sign in). And map the session back to a more long term storage when the user changes the config.
C.
Related
I haven’t written the code yet, as I am new to using cookies and trying to wrap my mind around the concept of coding cookies. I’m going to be combing the use of cookies and session data for my login system.
Because there is a time limit set in my cookies, I would think this would need to be updated periodically to keep the cookie active.
My plan:
User Logs in
Cookies are set for user ID, a random token, and a random serial key, and IP address (should I include the IP?)
Cookie data is stored in a database for when cookie is retrieved to validate the information.
I’m setting cookies to be valid for 1 month.
How often should cookie data be updated and when would you recommend updating it?
Should I update every time the server checks to see if user is logged
in or should it be sparatic? Should it only be updated if a session
isn’t found and it checks for cookie validity?
I’m new to this, so any info would be helpful before I start writing this code.
First of all, I would suggest a framework for developing anything in php and I wouldn't try to re-invent the wheel with things like cookies, when frameworks have code to deal with them already - be that Laravel, Codeigniter (in any order).
Setting the cookie for a month should be optional - i.e. give your user the choice whether this is a one time login, otherwise their account may be at risk, say they're using a public computer.
The most simple form, is to update a database whenever a logged in user refreshes a page, based on the session, not the cookie. The cookie is editable client-side, therefore should not be relied on for this updating mechanism. It can be trusted more so for the "remember me" feature, because you can assign specific user ID's to specific tokens/cookie data, meaning that you can then check to see an exact match, if not that means that somebody has tampered with the cookie.
I wouldn't recommend doing both - updating database and updating cookie. Set the cookie once, on login, then just play with a session database.
Not sure I would trust the IP, bearing in mind your IP can now be spoofed and changed via external software, on top of a simple router restart which may assign new IP's on re-connection. It could be an option, but it cannot be the only basis of authentication.
example from comments, clarification:
Say I am a user with ID 1, who has a mobile phone, a tablet and a PC.
Cookies are default valid for 14 days from date and time of login and are only inserted once, and are never updated thereafter.
I have enabled the "remember me" feature on all 3 of my devices as I logged in today -
mobile phone - 17.04.2018 at 12:00
tablet - 17.04.2018 at 12.20
PC - 17.04.2018 at 12.30
We travel to the future, and we the date is now the 28.04.2018.
11 days have passed.
I enable the feature on a new device, my partners phone for example.
The system should automatically remove the "stored" login from my mobile phone, even though 14 days haven't passed (because 3 is the maximum sessions that can be remembered per account).
The example I have provided only makes sense if you want to create a "secure" website which keeps control of not only active cookies but also of previous ones. Obviously, to be more secure I would't even give 3 remember me sessions, but only allow one or two.
If a limit is not what I was after, I would just give the user a settings page where they can deal with other active sessions on their account and give them the choice whether to remotely log those devices out or not.
On an e-commerce site with no username/login to persist cart data, would it be better to use the PHP $_SESSION variable or a browser cookie to persist items in the shopping cart? I am leaning toward $_SESSION since cookies can be disabled, but would like to hear thoughts from you.
Thank you in advance for your consideration.
Neither
No large sites would dare store a user's cart in a session or cookie - that data is just to valuable.
What customers are buying, when they select items, how many they purchase, why they don't finish the checkout, etc.. are all very, very important to your business.
Use a database table to store this information and then link it to the user's session. That way you don't lose the information and you can go back and build statistics based on users carts or solve problems with your checkout process.
Log everything you can.
Database Schema
Below is a simplified example of how this might look at the database level.
user {
id
email
}
product {
id
name
price
}
cart {
id
product_id
user_id
quantity
timestamp (when was it created?)
expired (is this cart still active?)
}
You might also want to split the cart table out into more tables so you can track revisions to the cart.
Sessions
Normal PHP Sessions consist of two parts
The data (stored in a file on the server)
A unique identifier given to the user agent (browser)
Therefore, it's not $_SESSION vs $_COOKIE - it's $_SESSION + $_COOKIE = "session". However, there are ways you can modify this by using a single encrypted cookie which contains the data (and therefore you don't need an identifier to find the data). Another common approach is to store the data in memcached or a database instead of the filesystem so that multiple servers can access it.
What #Travesty3 is saying is that you can have two cookies - one for the session, and another that is either a "keep me logged in" cookie (which exists longer than the session cookie), or a copy of the data inside separate cookie.
As pointed out by Xeoncross, it is very important to store any possible information for analysis. So one should not entirely rely on sessions and cookies.
A possible approach is-
Use sessions if not logged in
If the user is not logged in, you can store and retrieve the cart items and wishlist items from session using $_SESSION in PHP
Use database when logged in
If the user is logged in then you can consider one of the two options -
Store the cart item or wishlist item in database alone
Store the cart item or wishlist item in database as well as in session (This will save some of your database queries)
When user logs in
When the user logs in, get all the cart items and wishlist items from the session and store it in the database.
This will make the data persistent even if the user logs out or changes the machine but till the user has not logged in, there is no way to store the information permanently so it will not be persistent.
Getting required data
Whenever you are trying to access cart or wishlist do the following check -
If the user is not logged in then look into session
If the user is logged in, query database if you are storing in the database alone, otherwise you can just look into sessions if you are keeping session updated along with the database
I would store it in a SESSION. My wish list is rather long, and I am afraid that it will not fit in the 4K storage that a COOKIE may occupy. It forces you set the session time out to a longer period.
note: there are some countries (like the Netherlands, where I am) that have very strict policies about cookies, and you may be forced by legislation to use Sessions.
Some points to help:
Cookies:
info is persisted untill the cookie expires (what can be configured by you);
tend to slow down the communication between server and client, since it has to be exchanged between the two in every request/response;
its an insecure form of storing data and easy to sniff;
they also have a limit to store data.
Session:
all information is persisted in the server, thus not been exchanged with the client.
because it is not shared across the network, its a bit more secure;
all info is lost when the session ends;
If you are hosting in a shared host, you may have problems with session ending in the middle of a operation due to a push on the resources by any of the sites hosted on the same server.
I would personally go with sessions, since I'm assuming to be a small/meddium auddience page. If it grows, you would be better with a simple DB structure to store this data, with a maintenance plan to get ridge of unnecessary data (eg: clients that choose some products but don't do the checkout).
You might consider using both.
The drawback with $_SESSION is that the session is cleared when the browser is closed.
Use sessions, but attempt to populate the $_SESSION data from a cookie, if it's available.
I would use a session. If a user has cookies disabled then the session won't be able to start as the session ID is stored on the user's machine in a cookie.
There are some settings you may want to look at in order to attempt to keep the sessions for longer.
Prevent the session cookie from being deleted when the user closes their browser by running session_set_cookie_params() with the lifetime parameter set. This function needs to run before session_start()
You may also want to extend how often sessions are cleared from the server by modifying the session garbage collection settings session.gc_probability, session.gc_divisor, session.gc_maxlifetime either in php.ini or using ini_set()
If you have other websites running on the server and you modify the above garbage collection settings you will need them set in php.ini so they apply to all websites, or if you are using ini_set() then you might also look at saving these sessions to a different directory than other websites by modifying session_save_path(). Again this is run before session_start(). This will prevent the garbage collection of other websites clearing up your extended sessions for one particular site.
I would also recommend setting the following session settings in php.ini session.entropy_file = /dev/urandom, session.entropy_length = 256, session.hash_function = sha512. That should give you a cryptographically strong session ID with an extremely tiny chance of collisions.
And make sure you have an SSL cert on your site to prevent man in the middle attacks against your session ID.
Obviously a user could still decide to manually clear all their cookies which will take the session ID cookie with it but that's a risk I'd be prepared to take. If I was halfway through a shopping cart system and hadn't checked out, I wouldn't go and clear my cookies. I still think sessions are better than just using plain cookies.
The data is secure enough so long as you are the only website that has access to your sessions directory and your session ID is strong. And by extending the server's session storage time your data can persist on the server.
There are further measures you could employ to make your sessions even stronger. Regenerate your session ID every 20 minutes, copying the data over. Also record session IDs against IP addresses in a database and check to see if a particular IP address attempts to send more than X number of session IDs in a given time to prevent someone trying to brute force a session ID.
You could also store the data in a database linked by the session ID, instead of in a session file on the server. However this is still reliant on a session ID which is stored in a cookie and could disappear at any time. The only way to truly be sure that a user doesn't lose their cart is by having them login first and storing in a database.
I'm having a problem. I have a page with about 1,200 buttons, the website will not be a membership website, I just want to be able to keep track of each visitor to ensure that a button that they clicked on cannot be clicked by them again until 24 hours have expired.
I know i could use cookies, but thats too much for 1,200 buttons.
Here is what the buttons html are like:
<li>Button 1</li>
Do you have any suggestions -- I am open to almost any type of script, but know that this website was made with PHP?
Your choices for keeping track of a given browser with some sort of browser-identifying ID (so you might know who a given user is) are:
Cookies
Local Storage
Your choices for storing the state of the 1200 buttons are:
Server-side storage of the state that is given to the web page by the server
Cookies (probably have to collapse the data to one bit per button0
Local storage
So, for example, you could combine storing a browser identifing value in a cookie with storing the actual button state in a server-side database. Then, when the page is rendered, you look up the button state in the database for the browserID that is in the cookie and you either disable or remove the relevant buttons from the rendered HTML page.
You could do all the storage in a cookie by collapsing the 1200 buttons state to one bit per button. Using A-Z and a-z and 0-9 and a couple of symbols, you could easily have 64 values per character which would allow you to store the on/off state for 32 buttons per character so the on/off state for 1200 buttons could be stored in 38 characters which easily fits in a cookie. If you had to store a time/date for each button too, then that won't fit into a cookie so you'd be left to server-side storage or local storage.
FYI, I hope you realize that any client-side scheme is very easy to get around. In fact, if you're just trying to prevent a user from going to the same URL more than once, all they have to do is bookmark the original URL and they can go there as often as they like without even visiting your web page. Or, they can just wipe cookies or local storage. Or, they can just go to a different browser.
The only real way to prevent multiple visits is to require user authentication and validate (on your web server) that a given logged-in user is allowed to visit any given page before rendering the page. So, if you want to do this robustly, then it has to all be done server-side and you will need some sort of site login.
If you want to avoid a proliferation of up to 1200 cookies on the visitor's browser, you need to look into "sessions". A session stores a single ID as a cookie on the visitor's browser, and then uses this as a key to a larger store of data on the server. As well as being much quicker, sending less data to the browser means less chance for the user to see and mess with it.
PHP's session support is documented at http://php.net/manual/en/intro.session.php
Incidentally, note that it's entirely trivial to by-pass any restriction which relies on the absence of a cookie or similar in this way - for instance you can switch to another browser, use the browser's "clear history" or "private browsing" modes, etc.
For each user, I want to allow them to choose their preferences, such as which categories to show on their profile, which tags they want to see, etc. Would cookies be better than sessions because they don't expire when users logoff?
I think the best solution is to mix cookies and database - the last one for logged in users.
Cookies are fine, because the user doesn't have to log in on your website to have some preferences saved.
But if somebody will login to your page than you got ability to save his preferences in more stable source - server database. Then these preferences are available from every computer and won't disappear after "browser cleaning".
EDIT:
Don't use sessions - they are worse than both, cookies-based and database-based solution.
Why sessions aren't a good idea? First of all they rely on cookies (session id which required for proper work of sessions system is stored in cookie called SID/SESSID/SESSIONID (in most cases)) so whenever you clean cookies you also lose your session. Moreover session are available only for few minutes (from first page load to browser close or about 20 minutes of inactivity on website) while cookies may be available for few months or even years!
So how should you do that?
There are two scenarios:
When user is not logged in:
Then when he change some preference store it just in cookie
When user is logged in:
Then when he change some preference just save it in database:
INSERT INTO preference (user_id, key, value) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE value = ?;
That's example for MySQL but you can do this the same in others RDBMS.
And how do you get final preferences?
// That's VERY unsafe code... you HAVE TO do necessary validation (this is only an example)
$preferences = unserialize($_COOKIES['preferences']);
if (/* user is logged in */) {
$databasesPreferences = result_of_query('SELECT key, value FROM preference WHERE user_id = ?');
$preferences = array_merge($preferences, $databasesPreferences);
}
Sumary
This solution gives you the most stable way for handling user preferences for both logged-in and non-logged-in users.
Cookies can have an expiration date. If there is no sensitive data in them then they're fine to use, however if you're storing thing like user id's, etc. that will be used in queries you're best off using sessions as they're stored on the server where people can't manually get at them.
You generally have three choices of where to save user preferences:
database
cookies
session
When deciding between these, each solution offers different behaviors in terms of:
persistence
locality (tied to a browser or account)
security
If you need longer-term persistence of these value, you should put them in the database. If you want them to not require a sign in, then cookies are a better choice. There really is no one right answer-- it depends on what you're trying to accomplish.
What is the point of using cookies when the user has logged off??? User needs to be using the website in order to read from the cookie and apply the settings. Once the user has logged in, you may query the database and store the options in sessions until the user has logged off.
My recommendation is that it's best that you use sessions as they are much safer.
Cookies are nice because they can last between visits or "sessions". However they are also user editable and readable globally. Storing sensitive data like a login, password, session id, etc can lead to a malicious site hijacking the session or users information. Also a crafty user could alter the cookie to change the privilege level or user who is logged in and impersonate them.
Sessions are very secure because they are stored server side away from the prying eyes of users and other web sites. They do have the limitation that anything that's stored in them disappears once the session ends.
When I do login systems I prefer to use a sessions. You can pull the user from the database and then load various user defined settings into the session.
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.