Computing.Net > Forums > Web Development > PHP and using sessions

Computer Problems? Computing.Net has over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to start participating now! Also, be sure to check out the New User Guide.

PHP and using sessions

Reply to Message Icon

Name: Phil Perry
Date: February 19, 2006 at 19:11:33 Pacific
OS: Linux (Red Hat)
CPU/Ram: Intel
Product: unknown
Comment:

I am developing an eCommerce Web site. I need to establish some sort of "session ID" the first time a viewer enters the site (on any page, not necessarily the Home page). Other data, such as the shopping cart contents, will be stored in a database, keyed off the session ID. I only need to reliably get the sessionID from page to page.

Using PHP, I can see if $sessionID is set, and create a new one if not (this should happen ONLY on the very first page visited). Then I pass $sessionID as part of each link and form. After, say, an hour of inactivity, a cron job deletes the database entry. I see two possible problems: one, if the user uses the browser "back" or "forward" keys to get to a page, the cached page is used. That by itself may not be a problem, as I should end up with the same $sessionID value as before. Pages are regenerated only on links (and forms?). If the user reloads the original entry page, once again $sessionID will be found to not be set, and a new one will be generated. The user would lose the shopping cart and other data.

Second, what if the user bookmarks a page with the query string that contains the sessionID? I suppose in that case I could check on each page that it's a current, valid sessionID (the cron job hasn't erased it yet). Is there any way to order a browser NOT to go back to the original entry page (the one with no $sessionID passed to it)? HTTP_REFERER doesn't help when a user is using the "back" button, so I can't see that I backed up into this page from a "lower level" one. If I get back to that original entry page, and detect that $sessionID is not set, is there any way to detect that I "back"ed into it? If I backed into it, or reloaded the page, I need to get the same session ID. As part of page navigation, I suppose I could offer my own "forward", "back", and "reload" buttons (which would make sure the target page gets $sessionID), but most users will probably use the browser's buttons anyway.

Another way would be to use session_start(); at the top of the page, but this sets a cookie, and I'd like to avoid that. Many users order their browsers not to accept cookies, so I don't want to rely on that.

Why Oh Why couldn't the HTTP definition make
it easy to establish a session, rather than treating each page as a standalone entity???? Does anyone have any suggestions? Is there any way to make a user-defined variable global across pages?

thanks, Phil



Sponsored Link
Ads by Google

Response Number 1
Name: SN
Date: February 20, 2006 at 08:14:29 Pacific
Reply:

The first thing to notice and to accept is that there is no solution to state management across http that is flawless...standard cookies, session cookies, session id in the url, etc all have their flaws, many of which you've already thought of and pointed out.

"Another way would be to use session_start(); at the top of the page, but this sets a cookie, and I'd like to avoid that. Many users order their browsers not to accept cookies, so I don't want to rely on that."
You don't have to rely on it, but most users don't set their browsers to refuse session cookies, which are different than your standard data cookies. You should use session cookies as a backup to putting in the session id in the urls.

Rather than try all the tricks to get around the limitations of session & cookie, design your interface bearing these two things in mind:
1. Make it so the user can create an account at any time during the shopping process, thereby guaranteeing that as long as they know their username and password, they won't lose their shopping cart items.

2. You can usually detect when the browser isn't accepting your cookies...Do so, and warn the user as early as you can that they need to create an account or enable cookies to add anything to their carts.

Also remember that you're on even ground with all the big guys as well...ebay and Amazon.com have the same problems you will, and they can't retain session state for all users any more reliably than you can. In addition, a user that has set their browser to refuse all cookies, including session cookies, can't reasonably expect any e-commerce site to work for them...Those users aren't your target demographic, and there's not much you can do for them.

Finally, one thing I've noticed in places I've worked that managed sessions state like you are is that you are likely to get killed when a hard-hitting bot hits your site...They'll flood your user tables since they'll get new session IDs every time - many of them strip that kind of stuff from the URLs before they make the page request. Make sure you account for this.

Good luck,
-SN


0

Response Number 2
Name: Phil Perry
Date: February 22, 2006 at 14:52:34 Pacific
Reply:

SN,

Thanks much for the long and well thought-out reply. I see your point that people who permit no cookies at all probably don't do much e-Commerce. What I think I'll do is try to establish a session cookie (session_start) and if that fails, grab a unique ID from the session database and pass that through the URL query string from page to page. I'll have to warn the user that they'll lose their shopping cart and other session data if they should reload the page they came in on, and they may have problems with PayPal if they choose to pay through that service. If they're merely browsing, that shouldn't be a problem.

Do you have any suggestions for dealing with the bots mentioned in your last paragraph? Are we talking about malicious DoS attacks, or accidental effects from catalogers (e.g., Google) trying to survey and index my site? If I suddenly find myself with huge session tables, would it be at all effective to start purging sessions (those with nothing in the shopping cart) every 5 minutes instead of every hour or two?

As for customer login, I'm considering that for the future, so I can deal with catalog mailings, store credit for refunds, and gift certificates. For the time being, I won't be doing that (as I should use SSL for entering account name and password, and my hosting service has limitations on using PHP with shared SSL).

thanks much, Phil


0

Response Number 3
Name: SN
Date: February 22, 2006 at 15:35:20 Pacific
Reply:

Hi Phil-
"Are we talking about malicious DoS attacks, or accidental effects from catalogers (e.g., Google) trying to survey and index my site?"
I was talking about the latter...Google doesn't usually strip that info off, but there are several less known, poorly written ones that don't accept cookies and will strip some GET variables out of the URL. There's really not anything you can do that's 100% surefire, but here are some ideas that can help:
1. Store IP address as well as session ID in the data...If you're willing to make the assumption that two hits coming from the same IP within a certain amount of time (a minute, for example) are the same user, then you can avoid creating new sessions that way.
2. Modify your robots.txt to exclude the pages you don't want bots to crawl...They're not obligated to obey, but most will.
3. Store user agent along with session id in your db...That way if one bot comes along that slams you and it has a unique user agent, you can block it.

I wouldn't actually do any of those right off the bat unless you're selling this solution to third parties...Otherwise cross this bridge when you come to it.

"What I think I'll do is try to establish a session cookie (session_start) and if that fails, grab a unique ID from the session database and pass that through the URL query string from page to page"
Then you're doing more than nearly every other ecom site out there...I think that should be plenty good enough.

"As for customer login, I'm considering that for the future, so I can deal with catalog mailings, store credit for refunds, and gift certificates."
My biggest motivation would have been order tracking...How does one check up on the status of their order without a login?

"my hosting service has limitations on using PHP with shared SSL"
So you are only using paypal for payment, I assume?

Good luck,
-SN


0

Response Number 4
Name: Phil Perry
Date: February 23, 2006 at 18:23:21 Pacific
Reply:

Hi SN,

I tried out the start_session() with $sessionID backup and it didn't work if cookies were turned off (actually, I had Opera set to ask me for permission for a cookie). Here's the code:

<?php
if ( !isset($sessionID) )
{
session_start();
print("DEBUG: session_id() returns ".session_id()."<br/>");
if ( "" == session_id() )
{
print("WARNING: unable to set session cookie. Do NOT reload this page, or you will lose your shopping cart contents and other session data!<br/>");
$sessionID=time();
}
}
?>
<html>
<head>
<title>Page 1 for session cookie with backup</title>
</head>
<body>
<?php
if ( isset($sessionID) )
print("enter page with \$sessionID set to $sessionID<br/>");
else
print("enter with sessionID = ".session_id()."<br/>");

if ( isset($sessionID) )
print("Go to [a href=\"pageC2.php?sessionID=$sessionID\"]Page 2[/a]");
else
print("Go to [a href=\"pageC2.php\"]Page 2[/a]");
?>
</body>
</html>

What happens is that a unique session ID seems to be set for each page... session_id()
shows a (different each page) 32 hex digit value even before I am asked for permission to set a cookie. So, it never sets $sessionID (to time() just for a quick test) and every page calls session_start() and annoys the user with a request for cookies. Any ideas on how to get around this? In general, there must be a way to tell that a cookie request was turned down. Does session_start() have a return code?

Thanks for the ideas on dealing with rogue bots. Next thing you know, someone will contract "rogue bots" to "ro-bots" to "robots"! :-)

Good point about needing a customer account for order tracking. If my volume gets big enough, I'll have to look into that. Of course, customers will receive an order (transaction) number, and could email me for a manual query. In the mean time, I wonder if it would be reasonable to have a Web page where you enter the transaction number and get back the order status, stripped of any personably identifiable information?

I am planning to use PayPal as a payment option. As I understand it, I just get the order information together and throw it over the wall in a query string to paypal.com. Hmm, come to think of it, would there be a limit on amount of data I can send to PP? I would like to send over the complete order details, but if that's too much data I may have to just send the total amounts over (A items, B cost, C shipping/handling, D tax, E grand total) and send the particulars in a separate e-mail.

regards, Phil Perry


0

Response Number 5
Name: SN
Date: February 23, 2006 at 19:56:52 Pacific
Reply:

Hi Phil-
OK, I did some experimenting...Apparently session cookies aren't differentiated as much as I thought.

It's a little difficult to figure out what your intention is in your code above...It's kind of half using PHP's sessions and half creating your own. Plus using register_globals is never a good idea - you should be using isset($_GET['sessionID']) instead of isset($sessionID).

First and foremost, did you know that PHP has this functionality built in?
Passing the session id.

Here is a more simple version I used, which worked ok for me in firefox with cookies turned off:
<?php
if (!isset($_GET['session_id']) )
{
session_start();
$session_id = session_id();
}
else
{
$session_id = $_GET['session_id'];
session_id($session_id);
session_start();

}
$_SESSION['data'] = "Hello World";
?>
<html>
<head>
<title>Page 1 for session cookie with backup</title>
</head>
<body>
<?php
print("enter page with \$session_id set to $session_id[br/]");
print("Go to [a href='cookieworked.php?session_id=".$session_id."]Page 2[/a]");
?>
</body>
</html>

One thing that I don't think you understand is how to figure out if cookies were set...After calling session_start(), session_id() will always return a valid session ID. Setting a cookie pushes it to the browser, but you don't know if it was accepted or not until the next request. Sites like amazon.com determine whether or not cookies were accepted by setting a cookie, then redirecting to a page that checks to see if it exists. On that second page, you can put out your warning.

As a side note, I tried going to amazon.com with cookies disabled and couldn't even navigate, much less shop - they just keep trying to redirect to the cookie setting page over and over until firefox gives up on them.

As for the annoying prompting to set a cookie, your best bet is to just see if $_GET['sessionID'] is set but session_id() is not set. If that's the case, then don't bother trying to set a cookie because they've already rejected the first one.

"I wonder if it would be reasonable to have a Web page where you enter the transaction number and get back the order status, stripped of any personably identifiable information?"
I suppose UPS and FedEx do it, so you'd probably be safe.

"Hmm, come to think of it, would there be a limit on amount of data I can send to PP? "
I think 2k is the size limit on URLs in general - but I thought that Paypal let you POST to their checkout system as well?

Good luck,
-SN


0

Related Posts

See More



Response Number 6
Name: Phil Perry
Date: February 25, 2006 at 17:45:00 Pacific
Reply:

Hi SN,

I tried out your code in Opera (set to ask permission for cookies) and it worked, except for one change I needed: at the top, in the "else" clause (session_id _was_ set upon entry), I had to remove the session_start(). Otherwise, it would ask _again_ for permission to set a cookie. Do you see any problem with what I did? What does session_start() do the second time around?

Does setting the "data" SESSION entry do anything magical, or are you just giving an example of something that can be done?

In Firefox, I also set it to ask for permission to set cookies from my test site. It asks permission to set a cookie the first time, and if I tell it "no", it behaves itself until I "back up" to the entry page (no URL query string). Then it asks me again for permission, and either way (yes or no) gives me a new session id. That's not good. With Opera, it seems to just use the cached page with the original session id, rather than reloading. I guess I need a method to ensure consistency whether or not pages are cached. Should I use a <meta> command to turn off page caching on my site? I kind of hate to do that...

I've been using an older PHP book to learn this stuff, an edition updated for the (then) new PHP 4, so it's possible I'm missing information. BTW, my hosting service is at 4.4.1. My intent was to pass an explicit sessionID in the URL _only_ if session wasn't working (cookie not set). On entry to the site (on any page), I would see if the URL query string had sessionID, and if it did, use it. Otherwise I would call session_start() and use the cookie if provided. Your method of snagging the session id from the system and always explicitly passing it seems to work just as well. However, I'm still worried about caching effects (and not calling start_session again).

By the way, since I'm looking in $_GET for the session_id, does that mean I have to use the GET action for any forms, rather than POST?

thanks, Phil


0

Sponsored Link
Ads by Google
Reply to Message Icon

PHP/CSS -- border color Monitoring web servers?



Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Web Development Forum Home


Sponsored links

Ads by Google


Results for: PHP and using sessions

PHP and POST www.computing.net/answers/webdevel/php-and-post/2024.html

PHP and Apache2 www.computing.net/answers/webdevel/php-and-apache2/7.html

PHP and Mysql to create Auto-links www.computing.net/answers/webdevel/php-and-mysql-to-create-autolinks/522.html