Reputation: 2606
When sending the user to a checkout page, they are switched from http://sitename.com
to https://sitename.com
.
As a result, $_SESSION
variables are lost.
The site has a valid SSL certificate which may or may not be of some use.
Upvotes: 64
Views: 72265
Reputation: 441
I have had this issue moving from http to https and I was able to solve this issue changing the website URL from http://example.com to https://www.example.com
adding the www to the URL solved this issue for me.
Thanks.
Upvotes: 0
Reputation: 1193
I have got a solution by this..Try it.
$_SESSION['test'] = 'test';
session_regenerate_id(true);
header("Location: /");// the header must be sent before session close
session_write_close(); // here you could also use exit();
Upvotes: 0
Reputation: 41
I had a similar problem, however, this solution was good for me, perhaps will help others in the future
add this in your php.ini
suhosin.session.cryptdocroot = Off
suhosin.cookie.cryptdocroot = Off
Upvotes: 0
Reputation: 1
Do you have a dedicated IP? on some shared environments the https and the http are routed through different servers, so switching actually loses access to the cookies since they're on different domains.
solutions would be: dedicated ip
forcing https on all pages at all times
Upvotes: 0
Reputation: 711
When you switch between the HTTP and HTTPS services on the same server, your HTTP session ID is not being passed to the HTTPS session. You can set it by passing the session ID from the HTTP page to the HTTPS page in one of three possible ways:
From PHP: session_start:
session_start()
creates a session or resumes the current one based on the current session id that's being passed via a request, such as GET, POST, or a cookie
When you are using sessions, you will normally start your script with session_start()
. If the browser has a session ID cookie set, session_start()
will use that session ID. If the browser does not have a session ID cookie set, session_start()
will create a new one.
If the session ID is not set(in your example, the browser is creating a new session ID cookie for the HTTPS session), you can set it using the session_id()
function. session_id()
also conveniently returns the session ID as a string. So
...
$currentSessionID = session_id();
...
sets the $currentSessionID
variable equal to the current session ID, and
...
session_id($aSessionID);
...
sets the sessionID cookie in the browser to $aSessionID
. from PHP: session_id
Here's an example with two scripts. One is accessed via HTTP and the other is accessed via HTTPS. They must be on the same server to maintain session data.
Script 1(HTTP):
<?php
// This script will create a session and display a link to your secure server address
// to transfer your session ID. In this example, the secure page to receive the session
// ID is located at http://www.yoursite.com/safePages/securePage.php
// Start a session using the current session ID stored in a cookie, or create
// a new session if none is set.
session_start();
$currentSessionID = session_id();
// Set a variable that will be retrieved with the HTTPS script.
$_SESSION['testvariable'] = 'It worked';
// $secureServerDomain is the domain of your secure server
$secureServerDomain = 'www.yoursite.com';
// $securePagePath is the path to the page that will receive and set the session ID.
$securePagePath = '/safePages/securePage.php'
echo '<a href="https://' . $secureServerDomain . $securePagePath . '?session="' . $currentSessionID . '">Click here to transfer your session to the secure server</a>';
?>
Script 2(HTTPS):
<?php
// Retrieve the session ID as passed via the GET method.
$currentSessionID = $_GET['session'];
// Set a cookie for the session ID.
session_id($currentSessionID);
// Start a session.
session_start();
// Test retrieval of variable set when using HTTP.
if (!empty($_SESSION['testvariable'])) {
echo $_SESSION['testvariable'];
} else {
echo 'It did not work.';
}
?>
For this to work the HTTP and HTTPS servers must use the same session data storage substrate (i.e. for the default files handler, run on the same physical machine with the same php.ini). There are some security flaws here, so I would not use this code to transfer sensitive information. It is just meant as a workable example.
When I ran into this problem before, I came up with the above as a quick fix, but I just remembered the original cause of the problem. I was going from http://www.example.com/page.php to https://example.com/page.php (notice the lack of "www"). Make sure that http://www.example.com/page.php will link to https://www.example.com/page.php and http://example.com will link to https://example.com/page.php.
PS, I didn't actually run these scripts so there may be a typo or two that prevents them from running properly as is.
Upvotes: 71
Reputation: 51638
Sounds like the session cookie is set to be secure. Cookies have a "secure" flag which, if set to true, means that the cookie won't be sent to non-https sites. PHP is probably using that for its session cookies. You can change this with the session_set_cookie_params function, or with the session.cookie_secure setting in php.ini.
Upvotes: 16
Reputation: 2348
You can manage session between HTTP to HTTPS or HTTPS to HTTP:
Transmit session ID between page using GET
POST session ID by POST
Use files to save sessions
Use Cookies for sessions
Use database to save session
Below example can be used to transmit using GET….
File : http.php ……………
<?php
session_start();
$sessionID = session_id();
$_SESSION['demo'] = ‘Demo session between HTTP HTTPS’;
echo ‘<a href=”https://www.svnlabs.com/https.php?session=’.$sessionID.’”>Demo session from HTTP to HTTPS</a>’;
?>
File: https.php ……………
<?php
$sessionID = $_GET['session'];
session_id($sessionID);
session_start();
if (!empty($_SESSION['demo'])) {
echo $_SESSION['svnlabs'];
} else {
echo ‘Demo session failed’;
}
?>
IE7 : This page contains both secure and nonsecure items
You have to use relative path for all static resource on page like css, js, images, flash etc. to avoid IE message secure and nonsecure items…
IE Message
Upvotes: 1
Reputation: 24071
Think about using HTTPS for all pages, that's the easiest way to avoid this problem and it will improve the security of your site.
If SSL for all pages is not an option to you, then you could use this approach: Switching between HTTP and HTTPS pages with secure session-cookie. The idea behind is, that you leave the session cookie unsecure (and therefore available to HTTP and HTTPS pages), but have a second secure cookie to handle the authentication. It's a good way to separate the two concerns "maintaining the session" and "authentication".
Upvotes: 1
Reputation: 9547
I'd recommend, in addition to what most have stated here about transferring encrypted information, looking at it the same as if you were transferring sensitive information through a 3rd party API. How do you know someone isn't spoofing the request? There are many protocols for truly confirming the authenticity of the request, depending on how sensitive your setup is. You're opening yourself up to accounts being compromised if you're not careful.
Even though it's on the same server, consider this:
When someone is following the link, form action, etc. that passes over the encrypted key, what would prevent someone from sniffing it BEFORE they get to the secured version of your site? If I were at a public WIFI spot, that wouldn't be too far-fetched. I could pretend to be your site, reroute requests to my own laptop, grab the token, and redirect the visitor back to where they came. They would assume it was a glitch, and would have no idea. Now I can login as them, and possibly go buy $10,000 worth of stuff with their credit card on file and ship it somewhere else. The degree of caution you take here should match the degree of sensitivity.
Also, make sure you expire your tokens (one use only, after X number of seconds, etc), but I would also consider using the Post-Redirect-Get pattern on both ends, i.e.:
Don't show the direct link on a page or in the form of the unsecured site, but show a link that will then redirect on the backend (and handle all the token/encryption stuff). When you arrive at the secured version, do the same (don't leave a "?token=asdfjalksfjla" parameter just sitting there in the URL; redirect it).
So, formal token-based systems were designed to solve this very problem, but implementing OAuth just for this might be overkill. Spend some time planning the potential vulnerabilities before executing. Just because it'd be really hard to guess the token doesn't mean it's impossible (or there couldn't be collisions, etc.), so plan accordingly.
You also might need a more sophisticated session management system than PHP's built-in handlers. I don't know if you can force PHP to continue a session across multiple visits (switching protocols is treated that way).
Upvotes: 1
Reputation: 98
Don't worry this is a normal behavior because HTTPS is meant to be secure and it is doing his part.
Below are some tricks through which you can maintain the session while switching from HTTP to HTTPS.
Transmit session ID between page using GET
POST session ID by POST
Use files to save sessions
Use Cookies for sessions
Use database to save session
Hope you will get something through my reply.
Upvotes: -1
Reputation: 2543
You can't pass session values between different domains. You must use http post-get or a database to pass your values. For security, you can concat all your values in a string and use
sha1($string)
and post it alongside your values and calculate the sha1 for the values other page gets, then compare the hashes.
Post method on different domains cause browsers to show a security message, so don't use that.
Using url for get method is not safe, you would need to ask for a password on the redirected page for allowing the get parameters in your system.
Do not use cookies if you need security.
The way I am suggesting is, save the values in a database and generate a key, then make your redirection link using your key, forward the users page with a get parameter which has the key, then the page user is redirected to gets that key, fetches the data and removes the key. you can generate a key with sha1
PAGE 1---
$key=sha1($allvalsconcat);
//insert your session values to a database also the key in a column
header("Location: page2.php?key=".$key);
PAGE 2---
// select from database where key=$_GET["key"];
// delete from table where key=$key
this is pretty secure.
the things that can happen: a script entering random values for the parameter "key" to make your website load the data into your memory?
This is not going to happen because you delete the entry after using it. Some common misconception is that get values are unsafe and should always be avoided.
you can set the table engine type to "memory" in mysql if you want performance perfection.
Upvotes: 1
Reputation: 19979
The following solution assumes the secure and non-secure servers have access to the same backend services (cache, database store, etc).
We had to deal with this same issue when sending a user to our checkout flow when they were done shopping. To solve this, we put in place a caching layer and cached all the pertinent data. For example, we would glean the product ids and user id from the session values, serialize them, create a hash, and finally store the session data within cache using the hash as the key. We would then redirect user to the secure site with the hash in the url.
When the user ended up on the secure site we would attempt to pull the data out of cache based on the hash. Then with the user id and product ids we could load all the pricing and description data out of the database and present to the user for final checkout review.
There is an inherit risk in that the cache data is volatile, but we have never had any issues with it as the redirect happens quickly.
Upvotes: 6
Reputation: 14250
We had this issue as well. It turned out to be because we were using the suhosin patch on our PHP installation. We fix it by setting suhosin.session.cryptdocroot = Off
in /etc/php.d/suhosin.ini
.
For the suhosin manual about suhosin.session.cryptdocroot
see http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.cryptdocroot.
We originally found the fix from this blog post: http://www.yireo.com/blog/general-news/315-switch-between-http-and-https-looses-php-session.
Upvotes: 12
Reputation:
Looks like your session cookie is created with the secure flag, but there's something with the url of your checkout page due to which the session cookie isnt being passed over.
Or probably, your session cookie isnt secure - just that the url of the checkout page is different enough (http://mysite.com vs http://www.mysite.com) that the browser isnt sending the cookie.
If you'd like to read more on flipping over from http to https and vice versa - do take a look at at my writeup on selective ssl :-)
Upvotes: 1
Reputation: 7543
By default I would expect a browser to treat connections to http and https as completely different sessions. Although the convention is that http://someUrl/ and https://someUrl/ will point to the same page it isn't guaranteed. You could have completely different sites running on port 80 (http) and port 443 (https).
I don't know PHP, but generally I would not expect session variables to be freely available between secure and non-secure sessions e.g. I wouldn't expect the credit card number from my last checkout to be available to all the subsequent insecure pages I visit.
Forgive the non-authoritative answer but I thought I'd chuck in my 2c since there aren't many answers.
Upvotes: 0
Reputation: 93328
This may not be possible since the cookie seems to be getting lost. The browser you're using must think it's for a completely different domain.
What browser are you using specifically?
Upvotes: 0