Help getting PHP sessions to persist after being taken off-site
we're working on a payme开发者_高级运维nt gateway system with PHP. We use sessions to store the shopping cart data. The system takes you off-site to the payment processor's site, and then return you to your site. On most hosts, we have no issues when we arrive back at our site and having the session data still be there. On those with an issue, turning off the PHP session referer_check has worked in the past. We don't really want to have to include the PHPSESSID as a GET variable, and hope to avoid that. What I'm looking for is what other server configurations would cause the session to be killed, and any other workarounds there might be.
Thanks for your help.
Using cookie-based sessions there's a few possibilities:
- What domain is the cookie set for? mysite.com and secure.mysite.com are not the same.
- Does the problem occur on all web browsers for a given web host?
- Are you calling
session_regenerate_id
at any point? - Are you writing out the session cookie and redirecting to the payment processor from the same PHP page? Perhaps the web host is not sending out the correct headers. I'd suggest loading Firebug and checking that the session cookie in the browser matches the current session id on the server.
- When you run
phpinfo()
on the problem web host doessession.refer_check
actually have the desired value?
There's a whole lot of possibilities. Here's all the session-related PHP runtime settings many of which could be causing a problem:
http://www.php.net/manual/en/session.configuration.php
I've got the same issue and it was related mostly to cookie lifetime and cookie domain, www.example.org is not the same as example.org for IE, for example.
This a a very shadowy area of PHP security - how to persist the session without exposing a cookie or session id in the url? Unfortunately, the only somewhat safe solution happens to be with a cookie but I'll try and explain a way to make it as safe as possible.
Before the user goes off-site you need to prepare your database to accept them back without needing to provide login details again - create two columns in your user table - "key" and "timeout".
Now, as a user prepares to leave the site through your payment gateway, you need to update their record in the database - generate a unique key to store.
$key = md5(uniqid(rand(), true));
Store this in the datebase along with a timeout (say, an hour or two, or even a whole day - whatever you need). So long as they return within the specified timeframe and can produce the proper key the system will continue to recognize the user and you don't have to worry about logging in again.
Now we need to set a cookie with the same key and, say, a salted md5 hash of their username (just in case). Make sure to give it the same timeout that you gave their record in the database (you don't want old cookies with sensitive information lying around forever).
Once they've returned to the site grab the cookie with the unique ID and their hashed username and compare it to the key/timeout combination in your database. If they match, all is well. Then delete the cookie.
No cookie no session, just use an uniq id sent as an additional parameter or attribute to the payment system ( usually tx id could also do ) , on the return page url write an function to identify the uniq ID received and compare, if true create a new session for the user.
As for session timeout problem, it must be the length of time configured in the server. You may need to review the php.ini file of the server.
I have got to know that the following can alter this time:
php_value session.gc_maxlifetime 72000 /* I have not tested this */
I think you can use my method to create a fingerprint id on user session using the following script on the page before leaving out from the website and on the page returning.
$string = $_SERVER['HTTP_USER_AGENT'];
$string .= 'GHYU&*%HHD#JSFHJJFD(*JFJ'; // any long value
/* Add any other data that is consistent */
$fingerprint = md5($string);
if (isset($_SESSION['HTTP_USER_AGENT']))
{
if ($_SESSION['HTTP_USER_AGENT'] !== $fingerprint)
{
/* Prompt for password */
session_destroy();
header("Location:"."URL/PATH/TO/LOGIN");
}
}
else
{
$_SESSION['HTTP_USER_AGENT'] = $fingerprint;
}
精彩评论