Browser: Cookie lost on refresh - php

I am experiencing a strange behaviour of my application in Chrome browser (No problem with other browsers). When I refresh a page, the cookie is being sent properly, but intermittently the browser doesn't seem to pass the cookie on some refreshes.
This is how I set my cookie:
$identifier = / some weird string /;
$key = md5(uniqid(rand(), true));
$timeout = number_format(time(), 0, '.', '') + 43200;
setcookie('fboxauth', $identifier . ":" . $key, $timeout, "/", "fbox.mysite.com", 0);
This is what I am using for page headers:
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Thu, 25 Nov 1982 08:24:00 GMT"); // Date in the past
Do you see any issue here that might affect the cookie handling? Thank you for any suggestion.
EDIT-01:
It seems that the cookie is not being sent with some requests. This happens intermittently and I am seeing this behaviour for ALL the browsers now. Has anyone come across such situation? Is there any situation where a cookie will not be sent with the request?
EDIT-02:
Here are the HTTP Headers:
Request Method:GET
Status Code:200 OK
REQUEST HEADERS
Accept:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Referer:http://fbox.mysite.com/dashboard
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US)
AppleWebKit/532.5 (KHTML, like Gecko)
Chrome/4.1.249.1045 Safari/532.5
RESPONSE HEADERS
Cache-Control:no-cache, must-revalidate
Content-Length:8903
Content-Type:text/html
Date:Tue, 06 Apr 2010 09:25:26 GMT
Expires:Thu, 25 Nov 1982 08:24:00 GMT
Last-Modified:Tue, 06 Apr 2010 09:25:26 GMT
Pragma:no-cache
Server:Microsoft-IIS/7.5
X-Powered-By:PHP/5.3.1 ZendServer
Thanks again, for any guideline.

The only thing I can think of, having seen your header information, is that PHP is outputting something before you set the cookie. If that is the case, setcookie should return false and you'll get a warning "Cannot send session Cookie - headers already sent" As Bart S. suggests, turn on error_reporting(E_ALL) and try outputting the return value of setcookie to verify this isn't the case.
Also, try just using setcookie in the basic case with just a name and value and check the response headers again. Then cut out all of your code except for the setcookie and if that works, bring all your code back using divide and conquer :)

One question, one suggestion -
Question - why are you doing the number_format(...) on the time(), since a time() + 43200 should be sufficient.
Suggestion - Have you looked at the clocks between the client and the server. Since you're only giving a 12 hour difference between the two, if there is a big clock skew or a disagreement on when GMT is between the two machines you might find that you're sending a cookie that is destine to expire in the very near future.

The way you handle your cookies is completely fine, everything seems okay in your code, the problem seems to lie with Chrome.
Although Chrome Issue# 3014 deals primarily with a Java applet, it seems that's what you are experiencing.

I've seen an issue similar to this before. I would double-check to see if the path is correct.
I'd imagine a www.domain.com is different from domain.com , as is www.domain.com/ (with trailing forward-slash)
Beyond that, check that PHP has access to write it's sessions to file with proper write permissions (it's a different directory depending on distro, but phpinfo() should tell you what directory it is trying to use. )
I've run into both of these before. The first one gives no error and seems to mimic what you're experiencing, the second one gives a file-write-access error of some sort but if errors aren't displayed you might not see that.

Is your application served from the http protocol or file:// ?
Chrome does not store cookies with local apps, and that's by design. You can change this behaviour with the command line switch:
--enable-file-cookies

Related

HTTP headers printed on top of page (Microsoft Edge)

The following 'code' is sometimes (random) printed on a webpage after refresh.
>HTTP/1.1 200 OK
>Date: Fri, 18 Mar 2016 09:05:03 GMT
>Server: Apache
>X-Powered-By: PHP/5.3.6-pl0-gentoo
>X-Frame-Options: DENY
>X-XSS-Protection: 1; mode=block
>X-Content-Type-Options: nosniff
>Expires: Thu, 19 Nov 1981 08:52:00 GMT
>Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
>Pragma: no-cache
>Keep-Alive: timeout=15, max=86
>Connection: Keep-Alive
>Transfer-Encoding: chunked
>Content-Type: text/html
>5
(the last number, 5 in this case, is random, the rest is constant.
This is what I tried to solved this annoying 'bug?':
Removing HTML <head> contents
Removing HTML <body> contents
Removing AJAX (XHR) calls
Updating Smarty (engine that parses the templates)
PHP trim() around output to prevent unnessary spaces before or after <doctype> and <html> tags
Killing almost all PHP code (this is to much to explain here, but since I stripped it down complety I am 99% sure it is not the serverside (PHP) code)
Looking for PHP functions that are able to print these headers (greps for headers_list, getallheaders, apache_request_headers, etc.)
Tried multiple pages, same results, no matter its contents.
My customer sees the seem results on Microsoft Edge browser.
Updated other components, like browser detection
Added PHP ob_start();
Validated HTML
Made sure to clean Javascript console errors (now clean)
Gave a go on WireShark for Windows, to look at what headers are received, but this was to difficult for me. (should I retry?)
This problem sounds a lot like mine, but wasn't helping to fix mine: bugzilla DOT mozilla DOT org/show_bug.cgi?id=229710
Checked other Stack Overflow questions. Could not find a matching question/solution.
More, which I forgot :)
Notes:
The site is server over HTTPS with a valid certificate.
Here is the site link: https://www.10voordeleraar.nl
Attached screenshot links below.
The funny thing is, this only happens on Microsoft Edge, sometimes. It is behaving properly on all other browsers, so do my other sites.
Regards,
Laird
Screenshots:
Printed HTTP headers example on site top
Printed HTTP headers example in DOM inspect

sessions not working

So I had developed a basic site, using $_SESSION superglobal variable for the logging in.
so the code basically after checking the login details are valid i store the users details into the session like so:
note I am starting the session before storing these values.
$_SESSION['myusername'] = $myusername;
$_SESSION['myuserid'] = $userid;
$_SESSION['logged_in'] = true;
$_SESSION['mystatus'] = $res['user_status'];
it all worked fine, throughout the time i made the site and tested etc.
now all of a sudden, the sessions are not working, so obviously the users cannot get access after logging in because the site is checking data which isnt in the session.
on the page I store the data like above, straight after i can use this:
echo "username".$_SESSION['myusername'];
echo "status".$_SESSION['mystatus'];
and its there. But when the user is directed to another page and i try:
<?php
session_start();
include ('functions.php');
echo "username".$_SESSION['myusername'];
echo "status".$_SESSION['mystatus']; ....
the values aren't in the session. I have checked that the session id is the same, which it is.
This has always worked, so I am really puzzled.
somebody please help.
EDIT
request header & response header from firebug (page where session appears to be empty)
Response Headersview source
Date Sat, 11 Jun 2011 15:18:48 GMT
Server Apache/2.2.3 (Red Hat)
X-Powered-By PHP/5.1.6
Expires Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma no-cache
Content-Length 3772
Connection close
Content-Type text/html; charset=UTF-8
Request Headersview source
Host students.ee.port.ac.uk
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-gb,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Cookie PHPSESSID=1jqqa2oeivq76h2vhtk4uflkv1
Authorization Basic ZWNlNzAxNDE6cGllczRtZTIy
So it seems you have a problem with keeping your session on a second request.
Session tracking is done via cookies, you should check (with Live HTTP Headers or firebug) the real cookie content sent by the server. In this cookie check the path setting and the server name given, check as well time validity settings, if something is wrong there the browser won't send back the cookie and you'll get a new session on each request.
The web developper Toolbar contains some nice cookie tools as well, where you can display a page containing all cookies details for a given page. If the cookie receveid is not there then the browser assume this cookie is not related to this page. Most of the time a php setting is enforcing the cookie.domain setting to something other than the used DNS.
Given the fact that you haven't changed a thing in the last few weeks and that it used to work, you should check that your server didn't run out of disk space. If it did, it may create a reference to a session but might not be able to serialize the data to disk once the page has been rendered.
This could explain why outputting the $_SESSION[...] works on the same page and why the cookie is set in the response.
Check whether the session id on the second request is the same as the one on the first request.

html page not getting cookies through libcurl

i modified my previous code. you can see my previous post if your intersted setting cookie through curl
But here is a fresh beginning my new code looks linke this
i have a php file using curl like this
<?php
$ch=curl_init();
$url="http://localhost/javascript%20cookies/test_cookies.php";
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_COOKIEFILE,dirname(__FILE__) . "/cookie.txt");
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
curl_exec($ch);
curl_close($ch);
?>
the file test_cookies.php looks like this
<?php
if($_COOKIE['user']==1)
{
header("Set-Cookie:user=1; color=blue");
header("Location:http://localhost/javascript%20cookies/test_cookies.html");
}
?>
the file test_cookies.html has some javascript that checks for cookies and if it finds those cookies then it displays the text accordingly.
the php file with curl code is sending the cookies and the test_cookies.php is setting the cookie and redirecting to the page test_cookies.html but this page is not receiving the cookies and thus it is not not showing the content accordingly.
can somebody tell me whats the problem now?
here are the headers i get displayed in firefox on setting CURLOPT_HEADER to true
HTTP/1.1 302 Found Date: Mon, 16 May 2011 15:03:59 GMT Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 X-Powered-By: PHP/5.3.1 Set-Cookie: user=1; color=blue Location: http://localhost/javascript%20cookies/test_cookies.html Content-Length: 0 Content-Type: text/html HTTP/1.1 200 OK Date: Mon, 16 May 2011 15:03:59 GMT Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 Last-Modified: Mon, 16 May 2011 12:13:24 GMT ETag: "11000000013d0c-493-4a363950a70f3" Accept-Ranges: bytes Content-Length: 1171 Content-Type: text/html
you can see that there are two set of headers displayed.is this because i am making 2 calls to header?
It is not clear what you are trying to achieve with the code. You'd get better help if you explain why you are doing this. It is probable that your approach is wrong and you could get the ultimate result with a different/simpler approach.
And now to answer your question, this is what happens:
From your browser, you send a GET request to curl.php (the name I use for your first file),
curl in that file checks cookie.txt and finds user=1, so it sends a GET request to test_cookies.php and sends the cookie with the request
test_cookies.php sees that user=1 is true, so it sends a header to curl.php and asks it to set two cookies: user=1 and color=blue (for the first cookie this is pointless, user=1 is already set, but let's ignore this as no harm is done)
You have not set CURLOPT_COOKIEJAR option, so when curl.php receives the set cookie header it does not give a damn (nothing happens)
Next, test_cookies.php sends a redirect header to curl.php, since you have set CURLOPT_FOLLOWLOCATION,1, curl.php sends another GET request, this time to get test_cookies.html
Content of test_cookies.html is returned to curl.php,
curl_exec($ch); causes the returned content (source of test_cookies.html) be echoed back to your browser,
Your browser parses what it received and the javascript is executed. It checks for a cookie named user and does not find one, so it displays content for when there is no cookie (because there isn't).
Now, you may wonder what happens if you add:
curl_setopt($ch,CURLOPT_COOKIEJAR,dirname(__FILE__) . "/cookie.txt");
What happens is that your cookie.txt will be updated in step 4 and will have two cookies; user=1 and color=blue. But this does NOT give you the result you expect. Because header("Set-Cookie:user=1; color=blue"); is instructing curl to set the cookie, and curl does this by storing the cookies in the file you specified in CURLOPT_COOKIEJAR option. So, even though you added that option, when you reach step 8 javascript will not find that cookie, because the browser you use does not know or care about your cookie.txt, it looks somewhere else to check if a cookie exists. In Google Chrome for instance the format is SQLite and for XP the cookies are stored in %USERPROFILE%\Local Settings\Application Data\Google\Chrome\User Data\Default\Cookies.
i will now explain what i was trying to do.
i had an html page that asked for some verification code and then it sent that verification code to a php script which on verifying the code set a cookie and redirected to the same html page.
the html page had some externally linked javascript which on checking the cookie value displayed the content of the page with some tweaking.
i am now writing the code for this
the html file with content and form
test_cookies.html
//some css,javascript and html and then a form
<form method="post" action="http://localhost/javascript%20cookies/test_cookies.php">
the php file which verifies the code
test_cookies.php
if($_POST['value']=="code")
setcookie("user",1);
if($_POST['value']!="code")
setcookie("user",1,time()-1);
header("Location:http://localhost/javascript%20cookies/test_cookies.html");
and now the php file with curl code
curl_cookies.php
<?php
$ch=curl_init();
$url="http://localhost/javascript%20cookies/test_cookies.php";
$post="value=code"; //here i have hard-coded the pst value for a demo but i could have got this from the user
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
curl_setopt($ch,CURLOPT_HEADER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$res=curl_exec($ch);
curl_close($ch);
preg_match('/Location: (.*)\s/',$res,$location);
preg_match('/Set-Cookie: (.*)\s/',$res,$cookie);
$cookie=rtrim($cookie[0])."; path=/ "; //path needed to be changed because curl_cookies.php and test_cookies.html are in different directories.
header($cookie);
header($location[0]);
?>
this finally worked and the browser is displaying the tweaked content. this thing taught me a lot about http.
Thanks to all who helped me when i was in dark.

Using cookies with CURL

I'm writing an "API" for a website which doesn't have it.
Basically, my PHP code logs into the website and grabs the data I need (two different transfers).
At login time, I'm getting a bit of a problem. The website sets a couple of cookies through HTTP, which I'm capturing using CURL's cookie mechanism.
This seems to work out nicely, except that they are also trying to set a cookie via javascript in that same response.
I don't need to parse the javascript since the cookie they set is entirely predictable.
What I need is to somehow tell CURL that this cookie exists, WHILE it stills maintains the other cookies.
Help? :)
After submitting the login details via curl POST, I get to these headers:
HTTP/1.1 200 OKDate: Fri, 20 Aug 2010 09:39:14 GMT
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 492
Set-Cookie: JSESSIONID=5DE1F32B3668DABB408BBEA10C28DBD5.testmmf1; Path=/merchantlogin
Set-Cookie: loginType=M
Connection: close
And this is the page content:
<script type="text/javascript">
var nextyear = new Date();
nextyear.setFullYear(nextyear.getFullYear() + 1);
document.cookie = 'login=' + document.referrer + '; expires=' + nextyear.toGMTString();
</script>
Notice the Set-Cookie and document.cookie parts.
Generate cookie file via code, and before making request to location witch requires that cookie add it simply through setopt with option CURLOPT_COOKIEFILE
You could set the cookie using curl_setopt and the CURLOPT_COOKIE option first. Of course doing this will erase your other cookies, but they'll be gotten back, right?
If you could get a hold of the current value of CURLOPT_COOKIE, you could append your cookie with a semicolon. But PHP doesn't seem to have a curl_getopt function.

Single PHP "exit;" statement prevents HTML5 video in Safari

Bizarre bug: in a PHP script that serves video files, I have a few test conditions (authenticate token, make sure file exists, etc.) before sending a "video/mp4" header and outputting an MP4 file.
If any of the tests fail, $fail is given a non-false value.
At the end of the tests there's this if statement:
if ($fail) {
exit;
}
This code works as expected in Chrome, but not in Safari. However (and believe me, I've tested this every which way), if I simply comment out exit;, as in:
if ($fail) {
//exit;
}
... the code works perfectly in Safari — the video immediately starts loading.
I'm sure that that if block is never entered, otherwise the script would stop executing, and I wouldn't be seeing the video/mp4 header (not to mention, it wouldn't work in Chrome). Further, whatever PHP is doing behind the scenes should be totally transparent to the browser. I thought maybe there was some issue with output, but I would have received a warning if I had outputted anything before the headers.
I've been seeing this behavior consistently for days — I've checked it probably 25 times in disbelief.
Surely there's something I'm missing?
UPDATE
To clarify the problem, I changed the code a bit:
$fail = true;
if ($fail) {
die('Fail');
}
Now we're guaranteed to hit the die() statement, and output "Fail". Here are the headers, as seen by Safari:
Connection:Keep-Alive
Content-Type:text/html
Date:Thu, 24 Jun 2010 23:31:28 GMT
Keep-Alive:timeout=10, max=29
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
Transfer-Encoding:Identity
X-Powered-By:PHP/5.2.13
("Fail" is outputted as expected, too.)
Now, when I comment-out $fail = true;, the headers change to:
Connection:Keep-Alive
Content-Length:47406944
Content-Type:video/mp4
Date:Thu, 24 Jun 2010 23:32:58 GMT
Keep-Alive:timeout=10, max=30
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
X-Powered-By:PHP/5.2.13
But the video still won't play! (QuickTime logo with a question mark over it.)
I think that's evidence enough that $fail remains false, and that die() is never executed.
Now, get this: if I again comment out die() (functionally equivalent to exit), so that my final code is:
//$fail = true;
if ($fail) {
//die('Fail');
}
... the video plays in Safari!
UPDATE 2
If I change the code to:
$fail = false;
if ($fail) {
die('Fail');
}
... to absolutely guarantee that $fail is false, it plays in Safari!
This behavior makes no sense to me, b/c if $fail was being set due to one of my verification conditions, then it would never output the video/mp4 header, as when I explicitly set $fail to true — and instead it would output a text/html page with the word "Fail" — right?
UPDATE 3
Here's all of the relevant code, just to be totally clear:
// verify
$fail = false;
$token = false;
$file_name = [rest assured that $file_name is correct];
if (!$file_name) {
$fail = true;
} else {
$file_name = '../video/'.$file_name;
}
if (!isset($_REQUEST['ts'])) {
$fail = true;
}
if (isset($_POST['token']) || isset($_GET['token'])) {
$token = isset($_POST['token']) ? $_POST['token'] : $_GET['token'];
} else if (isset($_COOKIE['token'])) {
$token = $_COOKIE['token'];
}
if ($token != md5(SALT_HASH.$_REQUEST['ts'])) {
$fail = true;
}
if (((int)($_REQUEST['ts']) + 60 * 10) < mktime()) {
$fail = true;
}
if (!is_file($file_name)) {
$fail = true;
}
if ($fail) {
die('Fail');
}
// output
$file_size = (string)(filesize($file_name));
header('Content-Type: video/mp4');
header('Content-Length: '.$file_size);
readfile_chunked($file_name);
exit;
HOPEFULLY THE LAST UPDATE / SUMMARY
This question is probably already too long, but I thought I'd try one last time to summarize how weird this is. There are 3 distinct responses:
1) If I hardwire a $fail = true; before if ($fail) die('Fail');, just so I have a baseline for failure, I get a text/html header, and the word "Fail" is outputted as expected.
2) If I leave the code as it is above, I get a video/mp4 header, but a broken video in Safari (it will play in Chrome).
3) Finally (and this is based on new testing I did today), if I comment out $fail = true; in the token-verification conditional, I get a video/mp4 header, and the video plays in Safari. Now, I figured there must something wrong with the token verification — but when I hardwire in another test to echo the value of $fail after the test, it's still false! The conditional is never entered (I also just put a straight die('!'); instead of $fail = true; — and I still get a video/mp4 header).
I simply cannot believe that commenting out code that never gets executed could cause a distinct response — and furthermore, that it would play in Chrome, but not in Safari; whatever's happening server-side with PHP should be completely transparent to the browser.
Crazy.
AHA!
I added some logging to my script, and it turns out that when serving HTML5 video, the browser makes two requests.
Here's the two (successful) requests from Chrome:
Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed
Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed
And here's the two from Safari (first successful, 2nd fails):
Fri Jun 25 17:41:32 2010 Browser: [Apple Mac OS X v10.6.4 CoreMedia v1.0.0.10F569] Fail: [0] Token: [6374fba3d9eac7d94de9741db76953c6] Timestamp: [1277509291]
Fri Jun 25 17:41:32 2010 Verification passed
Fri Jun 25 17:41:33 2010 Browser: [QuickTime/7.6.6 (qtver=7.6.6;cpu=IA32;os=Mac 10.6.4)] Fail: [1] Token: [] Timestamp: [1277509291]
I have to go out right now, but I'm almost certain this behavior is the root of the bug. For some reason, the 2nd Safari request can't find the token.
It turns out that browsers make two requests to a <video> source before playing it. I was only seeing the headers for the first requests, hence my confusion. The reason the video played in Chrome but not Safari is because the agent that makes the 2nd request in Safari ("QuickTime/7.6.6 (qtver=7.6.6;cpu=IA32;os=Mac 10.6.4)") apparently can't read the same $_COOKIEs; whereas with Chrome, the $_COOKIEs are intact across both requests.
I still have a serious problem, in that the video plays only on desktop browsers, and not on the iPhone. I'm sure it's not an encoding problem, because if I access the MP4 directly, it plays fine; the problem occurs only when the video is outputted through PHP. Anyway, that's another question altogether.
The only reason for it to render a blank page would be that it does in fact enter the exit; statement. You mentioned an authentication token, could that be missing when testing in safari? Firebug and Safari's developer tools can also help you with debugging (check the response headers, etc).
Without the video/mp4 header, the server will send the default content type header, usually text/html, some browser may look at what's being served and ignore the MIME type.
Add error_reporting(E_ALL);to the beginning of the script, and use firebug or similar to examine the headers being sent.

Categories