Link to home
Start Free TrialLog in
Avatar of jporter80
jporter80Flag for United States of America

asked on

Webstore Cart HTTPS Problem

Im setting up a webstore and having problems with the items not staying in the cart at checkout.

http://www.lindco-usa.com/store/

It works fine if i put the site under regular HTTP throughout the check out.  But as soon as i activate HTTPS on checkout the items get lost.

Any ideas where to start?

using wordpress with wp-ecommerce plugin (getshopped.org)

This is my session settings:

User generated image
Avatar of jporter80
jporter80
Flag of United States of America image

ASKER

on a side note if i go to the store under https and hit add to cart... then refresh the page.. the cart clears.
set session.cookie_secure to on in your php.ini
Session variables are lost and the session id changes unless you set session.cookie_secure as ahoffman suggests.
Try installing this and running it to see how cookies work.  You may have cross-subdomain issues, as well as HTTPS issues.  See also the note about "secure" on this page.
http://php.net/manual/en/function.setcookie.php
<?php // RAY_cookie_example.php
error_reporting(E_ALL);

// RECEIVE FORM INPUT AND SET A COOKIE WITH THE NAME, VALUE AND LIFE FROM THE FORM
// MAN PAGE: http://php.net/manual/en/function.setcookie.php
// TO SEE COOKIES IN FIREFOX, FOLLOW SOMETHING LIKE TOOLS => OPTIONS => PRIVACY => SHOW COOKIES (OR "REMOVE INDIVIDUAL")


// REQUIRED AT PHP 5+
date_default_timezone_set('America/New_York');


// IF THE FORM HAS BEEN POSTED
if (!empty($_POST))
{
    // TIDY UP THE POST INPUT - CLEAN AND NOT MORE THAN 16 BYTES
    $name = substr(clean_string($_POST["name"]),0,16);
    $data = substr(clean_string($_POST["data"]),0,16);
    $life = clean_number($_POST["life"]);

    // BE SURE WE HAVE USEFUL INFORMATION
    if ( ($name == '') || ($data == '') ) die("MISSING INPUT: PLEASE <a href=\"{$_SERVER['PHP_SELF']}\">TRY AGAIN</a>");



    // CHOOSE THE COOKIE NAME, VALUE, AND LIFE IN SECONDS
    $cookie_name    = $name;
    $cookie_value   = $data;
    $cookie_life    = $life;



    // CONFIGURE THE COOKIE LIFE
    if ($life == 0)
    {
        // USE THIS TO MAKE COOKIE EXPIRE AT END OF BROWSER LIFE
        $cookie_expires = 0;
    }
    else
    {
        // USE THIS TO MAKE A PERSISTENT COOKIE
        $cookie_expires = time() + $cookie_life;
    }



    // MAKE THE COOKIE AVAILABLE TO ALL DIRECTORY PATHS
    $cookie_path	= DIRECTORY_SEPARATOR;



    // MAKE THE COOKIE AVAILABLE TO ALL SUBDOMAINS - DOMAIN NAME STARTS WITH DOT AND OMITS WWW (OR OTHER SUBDOMAINS).
    $x = explode('.', strtolower($_SERVER["HTTP_HOST"]));
    $y = count($x);
    if ($y == 1) // MAYBE 'localhost'?
    {
        $cookie_domain = $x[0];
    }
    else // SOMETHING LIKE 'www2.atf70.whitehouse.gov'?
    {
        // USE THE LAST TWO POSITIONS TO MAKE THE HOST DOMAIN
        $cookie_domain = '.' . $x[$y-2] . '.' . $x[$y-1];
    }



    // MAKE THE COOKIE AVAILABLE TO HTTP, NOT JUST HTTPS
    $cookie_secure    = FALSE;



    // HIDE COOKIE FROM JAVASCRIPT (PHP 5.2+)
    $cookie_http      = TRUE;



    // SET THE COOKIE
    if ( setcookie
         ( $cookie_name
         , $cookie_value
         , $cookie_expires
         , $cookie_path
         , $cookie_domain
         , $cookie_secure
         , $cookie_http
         )
       )
    {
        echo PHP_EOL . "<br/>SUCCESS!  THE COOKIE HAS BEEN SET AND WILL BE AVAILABLE TO THE NEXT PAGE LOAD";
    }
    else
    {
        echo PHP_EOL . "<br/>FAILURE!  THE COOKIE WAS NOT SET AS EXPECTED";
    }



    // AT THIS POINT, THE COOKIE HAS BEEN SET, BUT IT IS NOT AVAILABLE IN THIS SCRIPT
    // THE COOKIE WILL NOT BE RETURNED FROM THE CLIENT TO THE SERVER UNTIL THE NEXT HTTP REQUEST
    // THIS IS BECAUSE THE BROWSER SENDS THE COOKIE TO OUR SCRIPT BEFORE OUR SCRIPT STARTS RUNNING
    echo '<pre>';
    echo PHP_EOL . '$_COOKIE CONTAINS '; var_dump($_COOKIE);
    echo PHP_EOL . '$_POST CONTAINS ';   var_dump($_POST);
    echo PHP_EOL . 'THE COOKIE HAS BEEN SET WITH THESE VALUES: ';
    echo PHP_EOL . 'COOKIE NAME:    ' . $cookie_name;
    echo PHP_EOL . 'COOKIE VALUE:   ' . $cookie_value;
    echo PHP_EOL . 'COOKIE EXPIRES: ' . number_format($cookie_expires) . " == " . date('r', $cookie_expires);
    echo PHP_EOL . 'COOKIE PATH:    ' . $cookie_path;
    echo PHP_EOL . 'COOKIE DOMAIN:  ' . $cookie_domain;
    echo PHP_EOL . 'COOKIE SECURE:  '; var_dump($cookie_secure);
    echo           'COOKIE HTTP:    '; var_dump($cookie_http);
    echo "</pre>";
}


// END OF SETTING THE COOKIE - CREATE THE FORM IN HEREDOC NOTATION
$self = $_SERVER["PHP_SELF"];
$form = <<<FORM
<pre>
<form method="post">
COOKIE NAME: <input name="name" /> STRING
COOKIE DATA: <input name="data" /> STRING
COOKIE LIFE: <input name="life" /> INTEGER SECONDS
<input type="submit" />
<b>TO SEE THE EXISTING COOKIES <a href="$self">CLICK HERE</a></b>
</form>
</pre>
FORM;
echo $form;



// SHOW THE COOKIE ARRAY, IF ANY
echo '<pre>$_COOKIE CONTAINS '; var_dump($_COOKIE); echo "</pre>";



// UNRELATED FUNCTIONS TO TIDY UP FORM INPUT
function clean_string($string)
{
    return trim(preg_replace('/[^A-Z0-9_]/i', NULL, $string));
}

function clean_number($string)
{
    return trim(preg_replace('/[^0-9]/i',     0,    $string));
}

// ACTIVATE THIS TO SHOW THE SCRIPT CODE
// die( highlight_file(__FILE__, TRUE) );

Open in new window

im not sure what im exactly looking for but here is the file running>..

https://www.lindco-usa.com/cookietest.php

Also is it weird that i cant find the session.cookie_secure variable in my php.ini file?  should i add it? and make it on?
I set a value in the cookie and it worked for me in both
https://www.lindco-usa.com/cookietest.php and
http://www.lindco-usa.com/cookietest.php
Couple of man pages that might be helpful.
http://php.net/manual/en/session.configuration.php#ini.session.cookie-secure
http://php.net/manual/en/function.session-set-cookie-params.php

My sense is that if you turn on secure session cookies, your session will be lost if you switch from HTTPS to HTTP.  So the right strategy might be to test for HTTP in the scripts and if that is what you're using, redirect to the same URL using the HTTPS protocol header.
Yeah its like it refuses to pass from http to https from http to https.. if i clear all my cache and cookies and go to the store direct in https the cart works .... but is that normal?

here are my recent error logins when try to go from http to https checkout:

[Sat Mar 17 07:46:16 2012] [client 70.91.212.118] PHP Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: open(/var/lib/php/session/sess_ri9e0ikju21m8c94r310m52db2, O_RDWR) failed: Permission denied (13) in /var/www/vhosts/lindco-usa.com/httpdocs/wp-content/plugins/wp-e-commerce/wpsc-core/wpsc-constants.php on line 17, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
[Sat Mar 17 07:46:16 2012] [client 70.91.212.118] PHP Warning: Unknown: open(/var/lib/php/session/sess_ri9e0ikju21m8c94r310m52db2, O_RDWR) failed: Permission denied (13) in Unknown on line 0, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
[Sat Mar 17 07:46:16 2012] [client 70.91.212.118] PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
[Sat Mar 17 07:47:16 2012] [client 70.91.212.118] PHP Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: open(/var/lib/php/session/sess_ri9e0ikju21m8c94r310m52db2, O_RDWR) failed: Permission denied (13) in /var/www/vhosts/lindco-usa.com/httpdocs/wp-content/plugins/wp-e-commerce/wpsc-core/wpsc-constants.php on line 17, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
[Sat Mar 17 07:47:16 2012] [client 70.91.212.118] PHP Warning: Unknown: open(/var/lib/php/session/sess_ri9e0ikju21m8c94r310m52db2, O_RDWR) failed: Permission denied (13) in Unknown on line 0, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
[Sat Mar 17 07:47:16 2012] [client 70.91.212.118] PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0, referer: https://www.lindco-usa.com/wp-admin/post.php?post=59&action=edit&message=1
if i clear all my cache and cookies and go to the store direct in https the cart works .... but is that normal?
It would seem logical that you should be able to shop in both HTTP and HTTPS, with HTTPS being required only upon checkout.  However that may not be the way things work with the WP plugin.  If the plugin sets the cookie params to "secure" your browser is effectively being told that it cannot return the cookie over HTTP.  Hence, the session is lost.

So the only good solution may be to put the entire shopping experience behind HTTPS.  That is probably what I would do if I were seeing what you describe here.
well if i turn off https on check out the store works fine under http checkout and everything

go here http://www.lindco-usa.com/store/

then add an item to the cart and hit checkout.  the http version of the checkout works fine.  while on the check out page manually turn the url to https and then the cart empties... change it back to http and the cart magically reappears.

basically i cant pass sessions across http and https..

I understand that i can fix this by just forcing HTTPS on the whole store.  But i feel like there is a larger problem on want to fix here with the server.
It may be necessary to set the session cookie manually.  When I ran the cookie test script above, it worked across both HTTP and HTTPS, and that is the way it is supposed to work.  So I do not think there is anything wrong with the server.  Try this script and see if it works in a sensible way.
<?php // RAY_session_cookie_SSL.php
error_reporting(E_ALL);


// DEMONSTRATE HOW TO START SESSIONS THAT WORK IN HTTP AND HTTPS


// MAKE A DOMAIN NAME THAT OMITS WWW OR OTHER SUBDOMAINS
$x = explode('.', strtolower($_SERVER["HTTP_HOST"]));
$y = count($x);

// POSSIBLY 'localhost'
if ($y == 1)
{
    $host = $x[0];
}

// SOMETHING LIKE 'www2.atf70.whitehouse.gov'
else
{
    // USE A DOT PLUS THE LAST TWO POSITIONS TO MAKE THE HOST DOMAIN NAME
    $host
    = '.'
    . $x[$y-2]
    . '.'
    . $x[$y-1]
    ;
}

// START THE SESSION AND SET THE COOKIE FOR ALL SUBDOMAINS AND FOR BOTH HTTP AND HTTPS
$sess_name = session_name();
if (session_start())
{
    // MAN PAGE http://us.php.net/manual/en/function.setcookie.php
    setcookie($sess_name, session_id(), NULL, '/', $host, FALSE, TRUE);
}

// PROVE THAT THE COOKIE WORKS BOTH WAYS
$_SESSION["cheese"] = "Cheddar";
if (!isset($_SESSION["count"])) $_SESSION["count"] = 0;
$_SESSION["count"] ++;

// PUT UP TWO LINKS WITH DIFFERENT PROTOCOLS
$gost = ltrim($host,'.');
$ssl_link = 'https://' . $gost . '/RAY_dump_session.php'; // THIS IS A var_dump() SCRIPT
$www_link = 'http://'  . $gost . '/RAY_dump_session.php';

echo "<br/><a target=\"_blank\" href=\"$www_link\">$www_link</a>" . PHP_EOL;
echo "<br/><a target=\"_blank\" href=\"$ssl_link\">$ssl_link</a>" . PHP_EOL;


// SHOW WHAT IS IN COOKIE AND IN $_SESSION
echo "<pre>";
echo "COOKIE ";
var_dump($_COOKIE);
echo PHP_EOL;
echo "SESSION ";
var_dump($_SESSION);

// END OF PHP - PUT UP THE HTML FORM
?>
<form method="post">
<input type="submit" value="CLICK ME" />
</form>

Open in new window

> basically i cant pass sessions across http and https..
we have explained multiple times that this won't work due to obvious security reason which is handled proper by most modern browsers
this means if your application is setup properly, you cannot pass from http to https and vice versa with keeping your session data

to fix the problem please don't switch the schema, unless you 101% know that your application can handle it
so ahoffman.. why will this work on bestbuy.com?
http://www.bestbuy.com/site/Televisions/LCD-TVs/pcmcat193400050017.c?id=pcmcat193400050017

store is unsecure and checkout goes to https and the cart works fine.

you also mentioned to change my session.cookie_secure to on? will this work? if so why is that setting not in my php.ini?
If you make all of the pages involved in the cart, then the variables will stay set.
Ray.. i have your file setup here:

http://lindco-usa.com/RAY_dump_session.php

anything? lol
ALSO... if i tried to force https on the store directory to band-aid this problem it doesnt work with my htaccess:

# protect wpconfig at all cost
<files wp-config.php>
Order deny,allow
deny from all
</files>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} store
RewriteRule ^(.*)$ https://www.lindco-usa.com/store/$1 [R,L]

this doesnt work
> .. why will this work on ....
'cause the application is properly configured ;-)
that's what we want to help you

can you please post for each request: a) calling the page, b) adding item to cart, c) checkout
  1. the complete URL
  2. the Cookie header if any
  3. the response status line
  4. the Set-Cookie header if any

*please* only post these 4 lines for the request/response pair and not the complete request
why will this work on bestbuy.com?
My guess is that they are not using WordPress to run the Best Buy ecommerce site ;-)

Regarding this http://lindco-usa.com/RAY_dump_session.php I am seeing the  same session ID in both the HTTP and HTTPS versions of the script.
Im a little unsure how to get the info you requested.  i looked at the cookies via firefox and this is my results

Store Before any items added (http):

http://www.lindco-usa.com/store/
User generated image
Store After Item added (http)
User generated image
Store Checkout (https) - empty cart nothing there if i view the checkout in http the cart items show up
https://www.lindco-usa.com/store/checkout/
User generated image
Interesting... The session ID is the same.  Wonder where the server is keeping the $_SESSION array?  You might try using var_dump() to see what's in the session array.
Ray here is a var dump of the cookies and sessions

http://www.lindco-usa.com/cookietest.php

Go ahead and start a cart here:

http://www.lindco-usa.com/store/

Then go to

http://www.lindco-usa.com/cookietest.php

you can see the session info.

but if you switch to https on the cookietest.php page the session info disappears

the sessions are stored on the server at /var/lib/php/session

is there a permission problem with https accessing the session folder for some odd reason?
I can't think of any reason there should be a problem.  It appears that the browser is returning the session cookie to both HTTP and HTTPS.  But the HTTPS side has another interesting anomaly.  If I use the cart in HTTPS by manually typing the URL, then go to checkout, the cart is empty.
Sidebar note.  I have never encountered this before, and maybe because I have never used the session handler to hold a shopping cart.  The downside of using a session shopping cart is that a client who gets distracted can lose the contents of the cart when the session times out, and will definitely lose the cart if the browser is closed.  If you use a long-lived cookie and a data base to hold the shopping cart you can remember the client's preferences and cart items over more than just the instance of the browser life.
> Interesting... The session ID is the same.  
for sure, if only one application set it ;-)

@jporter80, unfortzunatelly the images are a bit useless as they only show the browser's internal view of the cookies, but wee need what's going on the wire verbatim
please user a browser extension/plugin like LiveHTTPheader in FF or fiddler in IE
if you have firebug it may work too
if you go to the store in https and add an item to the cart and refresh the page.. the cart empties to.

https://www.lindco-usa.com/store/

This is so FRUSTRATING.. something is wrong with https and sessions on my server.. its a VPS from media temple and the site is running fast cgi...

For me over http the cart stays full when i close the browser and reopen

UGHHH  on a related note  i had a very similar problem on the same vps with a different software under a different domain. you can read about it here: https://www.experts-exchange.com/questions/27539261/WHMCS-some-clients-not-able-to-login-PHP-Session-Problem.html

That ticket still has problems too with no resolution.. i did not think they were related but now im starting to think so... something wrong with the server setup. IMO but i dont know where to start.
See these links.
http://www.php.net/manual/en/function.session-start.php#91298
http://stackoverflow.com/questions/441496/session-lost-when-switching-from-http-to-https-in-php
http://www.bluehostforum.com/archive/index.php/t-1310.html
http://kb.mediatemple.net/questions/235/%28gs%29+PHP+Sessions+do+not+work+as+expected#gs

Regarding this: For me over http the cart stays full when i close the browser and reopen.  All instances of the browser share the same cookie jar.   So you must close all tabs and all windows to get the browser to empty the cookie jar.  This plays havoc with developers, but it is rarely a problem in real life, where your clients will just use one window or tab to use your site.
are youusing virtual hosts for http and https?
if so, are both using *exactly* the same configuration -in particular php.ini or equivalent- and are they using the same application (.php file)?
Forget my ignorance on this whole thing but I'm running a Vps server running plesk and each domain has a vhost.conf file.

For the domain in plesk for the domain I have the option checked to run ssl on the same directory and not separate like using a httpsdoc folder.

The site is running fast cgi on it. Does that answer your question?

One odd thing is I tried to edit the vhost file for that domain and change the The path for sessions and the changes didn't take effect when I did that. It kept the same session path as the image way above when I viewed a phpinfo page under the domain.
can you access phpinfo.php for http and https, please compare the settings
the session path could be a problem
Is it safe to post phpinfo pages here? I can show you the page that holds that info for you to see yourself.

But looks to be the same whether https or http.
Is it safe to post phpinfo pages here?
Sure.  You can take the link down later.  Phpinfo() does not expose anything that will get you hacked.  But if you're concerned about any exposure, you can just go through the printed output line-by-line and look for the differences.  You should find one line that is different (signals HTTPS) and this line will be absent in the HTTP version.
Here I the info page

Http://www.lindco-usa.com/phpinf.php

You can switch between http and https and looks to be the same.

Thoughts?
https://www.lindco-usa.com/phpinf.php
_SERVER["HTTPS"] is on and it's port 443
Look below _SERVER["REQUEST_TIME"] near the bottom.  I am not sure what i would be looking for here, but I notice some differences between the outputs.
so after consulting more with the VPS hosting provider, i feel i have nailed down where the problem is but wanting to see if the EE community would know away to fix the issue and not force https on the whole store.

here is Host information.

It appears the issue is that when a session is created with http, the session is owned by Apache. When the session is created via https, the session is owned by the FTP user.

I guess my question is, is there away to force http sessions to be created as the domain ftp user and not as apache?
> When the session is created via https, the session is owned by the FTP user.
is this --FTP-- a typo, or do the VPS people not know the difference?
I forget... Who is your hosting company?
@ahoffman. I'm not sure if it's a typo. I just copy and pasted fro
Their support ticket.

@ray it's media temple vps

@all what is weird now is I officially changed the session path for the domain to a root folder of the domain. And now permissions are opposite. Cart and check out work fine under https only but the cart session does not work under http.

I see that the user/group ownership of the sessions are under apache/apache and the folder is under the domain user and group which is also FTP user = lindcouser/pscalin
ASKER CERTIFIED SOLUTION
Avatar of jporter80
jporter80
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
because no one could figure it out.