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.
Related
I'm currently building a shopping cart for an eCommerce site and am wondering about the best way to persist user data in the session during the checkout process.
The user flow works is as follows:
shopping cart -> login/register -> select delivery address -> confirm -> pay
My issue is once a user is logged in, I want to display a list of their delivery addresses so they can select one. The easiest way to do this is querying the model by the user's id, but my concern is for security - my first thought was to store the user id in the session and then use this to retrieve the addresses. However there's nothing to stop another user potentially hijacking this id (just by guessing random numbers) and revealing addresses for other users. I could perhaps use their email address, but this too could potentially be guessed. Is my best bet to use a combination of the two, or is there a better way?
PHP has built-in session capability. It loads a unique cookie to the browser and allows you to keep all session data on the server-side via the $_SESSION array. The cookie ID is unique for the session, not the user, so it changes each time the user signs in (if the cookie has expired). If you conduct the session in https, it's very secure. Without https, the session is vulnerable to someone with the (special) knowledge and inclination to intercept the cookie data, though such an interception is not easy. Depending on how secure you want to be, running without https may or may not be acceptable for you.
You can read more about PHP session capability here:
http://php.net/manual/en/features.sessions.php
After reading a great post on PHP session security .I have two questions from the discussion.
1)$_SERVER['HTTP_USER_AGENT'] -This gets the information about the user's browser and other details and since a person can access their account from a different computer then how is it useful?
2)session_regenerate_id - This regenerates a session id , How should I use it ? Is the session_id deleted after a session has timeout or closed?
Thanks for all your help.I appreciate each view and response.
$_SERVER['HTTP_USER_AGENT'] , you can use this information for when you are using special features that may not work for everyone, or if they want to get an idea of their target audience. This also is important when using the get_browser() function for finding out more information about the browser's capabilities. By having this information the user can be directed to a version of your site best suited to their browser.
session_regenerate_id, When it renames the session id it does not remove the old session, leaving it active and potentially usable by a would be hacker. This does not pose a problem if the function is only used during new session create as the means of preventing session fixation, which is the intended use btw. However, it makes it completely useless if used on each session based request to prevent session leakage via HTTP_REFERER and similar, since the previous session id is still usable. It also means that changing the id on “actions” as some scripts to do prevent session theft also is pointless; in fact it doubles the amount of session ids for the same user making it only simpler to assume their identity. Furthermore it means that on every call to the function there is duplication in the number of sessions entries that will hang around until they are considered expired and removed by the garbage collection process.
The User-Agent is useful for determining the browser being used, which may lead to guessing some of its capabilities. For example, most mobile devices can be accurately identified by their browser's user agent (see WURFL), thus allowing a site's developer to direct mobile devices to the site's mobile version.
However, it can be modified by the user, so its value should be taken with a grain of salt as is the case with any user input.
session_regenerate_id() doesn't delete the session. It merely changes its id to a newly created one. To avoid having its old session file hang around until auto deletion by the system, you can delete it yourself by setting the optional function parameter to true. Its use is to avoid session fixation attacks where an attacker can gain access to an existing session's data by knowing and presenting its id to the server.
1) Sessions aren't bound to accounts, they're bound to browser sessions. You can use the user agent information to see if that someone other user agent is trying to hijack the session. However it's not fail-proof. You can also use things like the user's IP address (or a given range of it) to catch hijack attempts.
2) By calling session_regenerate_id from time to time, you reduce the chance of someone hijacking the session. This is especially true if the session ID is passed in the URL. For example let's say someone accidentally pasted a link to a chat with the SID in the URL. If you regenerate the session ID periodically, the users who saw that link can't hijack the session with it, as the ID would've changed already.
I'll try to answer your questions from the bottom up: session_regenerate_id() is useful in preventing session fixation attacks, where a malicious user who has obtained your session ID hijacks your session and can then act as you. When you regenerate the session, you can track the latest session ID in a database or something similar, and only allow access with the most current session ID (incidentally, if you regenerate sessid frequently enough, this will prevent users from browsing your site with multiple browsers/windows), otherwise old sessions will be available by default (unless you pass a boolean true parameter to the session_regenerate_id function call).
Some security-crazy people will suggest regenerating the session ID after every request, but you can also track a session variable that increments per request, and just regenerate every X number of requests (5 or 10 or whatever you determine is a sufficient amount for your security level). The other option is to regenerate the session ID during a privileges escalation, such as logging in.
As for HTTP_USER_AGENT, it is mostly useful in implementing browser/client-specific functionality (for example, displaying a "Get Chrome!" link when users visit your site using Firefox or IE).
I'm making a forum for learning mostly but hopefully it will have a couple of users some day.
What im wondering is should you use sessions or cookies for user authentication?
A cookie is a short piece of arbitrary data that the server sends through a header; the client stores it locally and sends it back on the next request. This mechanism can be used to maintain state from one request to the next even though HTTP itself is a stateless protocol. Cookies have two disadvantages: They offer only very limited amount of space (4 kB), and because they are sent back and forth in plain, a malicious client can fiddle with the contents before sending it back to the server, effectively making cookie data untrusted.
A session is a file on the server, identified by a unique ID which is sent back and forth between client and server so that the server can identify the client. The most popular way of sending the session ID is through the cookie mechanism, but it is also possible to pass the session ID through the URL (this is why you often see links that contain the URL parameter 'phpsessid'). This solves the two problems with cookies mentioned above: A file on the server can be as large as required, and the client cannot access the data other than through your own scripts.
Authentication is typically solved using cookie-based sessions; once authenticated, a new session is created, and the user ID is stored in it, and when logging out, the session is cleared and a new session ID is generated. Alternatively, you could store username and password in the session, and check them on every request.
Use a session.
A session is identified by a cookie, true, but not the same as storing user auth info in the client cookie, which is bad for security. A session cookie stores a guid or a hash in the cookie, then identifies the session (either database or file system based, depending on your server's php settings) based on that.
I recommend you store the primary key from your user table, not any other info, then look up the user info every time - this allows you to change their validation status, or security level on the fly while they are logged in; otherwise they will have to log out and back in before your administrative changes take effect for them - IE. you can't boot them.
Also, don't store the username/password, because that requires a less efficient query than by the indexed primary key (even if they are indexed as well).
They are essentially the same, working hand-in-hand. When you create a session..say through PHP, a cookie is created to store the session id too. On the other hand, you would create another cookie if you want to implement a "Remember Me" option to prevent your users from logging in every time.
I'm not a PHP expert, but Session and Cookie are related. In other programming languages you have the option of creating "Cookie based session" or "Cookie-less session". I'm not sure about PHP though so maybe you are referring to different concepts.
I feel using session is much more safe and easy then using cookies. The reasons are as follows:
1) In cookie we can only store a single piece of information, whereas in a session we can store as many information as we want.
2) Being stored on hard disk of user, cookies can be played with. Being a person interested in hacking, I have done that and gathered useful information about the user. Sessions cannot be used for such a thing.
If its a small amount of data (just one variable), I would use a cookie. Here is the code...
setcookie("cookie name", "cookie value or variable name", time+ 3600, "\");
this code sets a cookie that is readable for any of your webpages. It also will delete its self in one hour.
You can also see if the cookie exists like this (to see if it has deleted its self).
if (isset($_COOKIE['cookiename']))
{
}
to collect a value from a cookie...
$value = $_COOKIE['cookiename']; //makes a variable for this cookie for your program
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 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.