cookie delete problem - php

I have two simple functions to set and clear cookie.
private function _setCookie($value = null) {
$value = $value === null ? $this->getRandomId() : $value;
setcookie($this->getName(), $value, time()+10800, '/');
}
private function _clearCookie() {
setcookie($this->getName(), '', time()-10800, '/');
}
There is a page when accessed starts session and create a cookie as desired. When redirect call happens from different server to my page , delete cookie function calls internally above _clearCookie funtion.I checked setcookie returns true and I also tried to unset cookie in same method but cookie is still available when I reload page. I still can find that cookie in browser as well as firebug and print_r($_COOKIE)
Also I changed expire time to time()-(3600*24) as mentioned is some others threads but no change in my case. What am I missing here?

so when I mentioned 'redirect call happens from different server to my page' I was trying to mention it as back channel call. And being a back channel call, browser cookies were not getting identified I suppose and that is the main reason even if setcookie returns me true, actual cookie deletion from browser would never happen in such cases.

Related

How to change Cookies value at runtime [duplicate]

I have the following PHP function:
function validateUser($username){
session_regenerate_id ();
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
setcookie('username2',$username,time()+60*60*24*365);
header("Location: ../new.php");
}
And then I fetch the cookie:
echo $_COOKIE['username2']; exit();
(I only put exit() for debugging purposes)
Only problem, it's coming out blank. Any ideas?
UPDATE:
This is how the function is called:
if(mysql_num_rows($queryreg) != 0){
$row = mysql_fetch_array($queryreg,MYSQL_ASSOC);
$hash = hash('sha256', $row['salt'] . hash('sha256', $password));
if($hash == $row['password']) {
if($row['confirm'] == 1){
if(isset($remember)){
setcookie('username',$username,time()+60*60*24*365);
setcookie('password',$password,time()+60*60*24*365);
} else {
setcookie('username','',time()-3600);
setcookie('password','',time()-3600);
}
validateUser($username);
I didn't include all the if() statements to save some space.
try adding the path = /, so that the cookie works for the whole site not just the current directory (that has caught me out before)
example
setcookie('password',$password,time()+60*60*24*365, '/');
also make sure the cookie is the first thing being output
as advised in the php manual (this has caught me out before too)
Like other headers, cookies must be sent before any output from your
script (this is a protocol restriction).
Why you are having this problem
The problem comes from the fact that setcookie() doesn't set the cookies immediately, it sends the headers so the browser sets the cookies. This means that, for the current page load, setcookie() will no generate any $_COOKIE.
When the browser later on requests a page, it sends the cookies in the headers so the PHP can retrieve them in the form of $_COOKIE.
Simple, old solution
About solutions, the obvious one:
setcookie('username',$username,time()+60*60*24*365);
// 'Force' the cookie to exists
$_COOKIE['username'] = $username;
A better solution
I created a class, Cookie, that addresses the problems that setcookie() and $_COOKIE share:
// Class that abstracts both the $_COOKIE and setcookie()
class Cookie
{
// The array that stores the cookie
protected $data = array();
// Expiration time from now
protected $expire;
// Domain for the website
protected $domain;
// Default expiration is 28 days (28 * 3600 * 24 = 2419200).
// Parameters:
// $cookie: $_COOKIE variable
// $expire: expiration time for the cookie in seconds
// $domain: domain for the application `example.com`, `test.com`
public function __construct($cookie, $expire = 2419200, $domain = null)
{
// Set up the data of this cookie
$this->data = $cookie;
$this->expire = $expire;
if ($domain)
$this->domain = $domain;
else
{
$this->domain =
isset($_SERVER['HTTP_X_FORWARDED_HOST']) ?
$_SERVER['HTTP_X_FORWARDED_HOST'] :
isset($_SERVER['HTTP_HOST']) ?
$_SERVER['HTTP_HOST'] :
$_SERVER['SERVER_NAME'];
}
}
public function __get($name)
{
return (isset($this->data[$name])) ?
$this->data[$name] :
"";
}
public function __set($name, $value = null)
{
// Check whether the headers are already sent or not
if (headers_sent())
throw new Exception("Can't change cookie " . $name . " after sending headers.");
// Delete the cookie
if (!$value)
{
setcookie($name, null, time() - 10, '/', '.' . $this->domain, false, true);
unset($this->data[$name]);
unset($_COOKIE[$name]);
}
else
{
// Set the actual cookie
setcookie($name, $value, time() + $this->expire, '/', $this->domain, false, true);
$this->data[$name] = $value;
$_COOKIE[$name] = $value;
}
}
}
Then you can use it like this:
$Cookie = new Cookie($_COOKIE);
$User = $Cookie->user;
$LastVisit = $Cookie->last;
$Cookie->last = time();
And of course, you have to pass it around. Much better than having globals.
Here is the general syntax of setcookie
setcookie(name,value,expire,path,domain,secure);
Look at third argument, if you do not set it the script will take it to current working directory. So if you set a cookie without setting path at a.com/b/setcookie.php the cookie will not be available to a.com/checkcookie.php. What you are doing is setting cookie in a subfolder and the redirecting to a parent folder, look at ../, where it is not available hence the issue. How to avoid this? Normal procedure is to supply a path that is /, in your case supply / as fourth param. The fifth argument for your cookie will set it secure. http://www.php.net/setcookie has more explanation. This should fix your problem. Setting domain path to domain.com, will make the cookie available to everything under domain.com but not to something.domain.com. Set domain value to .domain.com, look at the dot preceding domain.com, will make it available across anything.domain.com. HTH!
Thought I would add another possible reason why a cookie may not be either setting or showing random functional behavior.
The following case may be applicable to some programmers having what appears to be an illusive cookie setting issue as a result of the incorrect usage of header_remove()
If you try to set a cookie before calling header_remove(), the cookie will never be created because you have also immediately destroyed the header that was set in order to create the cookie before it was buffered out to the client.
You may find when fiddling around that your cookie suddenly works for an unknown reason, so you need to understand the race-conditions around headers:
On first run you set a cookie and don't call header_remove() at all.
On a second run you do call header_remove()
You will find your cookie is now always set regardless of condition (2) and the number of times it is called because (1) happened first at least once.
The cookie will remain set until it either expires, is overwritten or unset()
The same will apply when modifying headers like a cookie value before the eventual call of header_remove(), you again will fail to set new values because they will be wiped before the response is buffered out to the user.
You need to set cookies and any other headers for that matter after a header_remove() not before.
Use header_remove() to cleanup ALL previously set headers in order to set new headers for a final output.
An example of scenario for such a case may be as follows:
Use header_remove() to alter a hierarchy of HTTP Response codes for a RESTFUL API where you are using axios with interceptors.
Your application sets a 400+ header error first, should the application error out at any point of execution.
Modify the header to a 200 when final desired execution point has been reached & a valid response is expected.
In such an event, it is likely you want to preserve all other previously set headers but clear out the HTTP Status (400?) code in order to set a new (200?) code for the final response.
If you try to set the header again in order to change the status code before removing the previously set header then you will get the "Headers already sent" error.
You can remove specific headers with header_remove, here is how to unset the status code and set a new code in stages:
// Set a default status code
http_response_code(500);
// Boot Logic runs - if fails here 500 is returned
// Authentication Logic - If unauthorized ?
header_remove('HTTP/1.0'); // Clear previous 500
http_response_code(401); // Set new status code
// else ?
// Return Data Logic - Success
header_remove('HTTP/1.0'); // Clear previous 500
http_response_code(200) // Set new status code
This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
this is how the structure looks
<?php
$cookie_name = "user";
$cookie_value = "Ahmed Moftah";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
?>
<?php
if(!isset($_COOKIE[$cookie_name])) {
echo "Cookie named '" . $cookie_name . "' is not set!";
} else {
echo "Cookie '" . $cookie_name . "' is set!<br>";
echo "Value is: " . $_COOKIE[$cookie_name];
}
?>
<html>
<body>
</body>
</html>
It might be a cache problem. Try closing the browser and opening a new one with the localhost file path. I had the same issue and my page was cached so the cookies weren't working, even though I could put in new code and see a change on the page. Very weird... Cleaning your cache might help, try that first. Then try a new browser, then try to go to your localhost:8080 index and hit refresh to see when the last page was modified.
If that doesn't fix it, try restarting LAAMP or XAAMP or whatever you are using.
This happens with the session cookies are disabled.
You can navigate to your php.ini file(changes depending on server. Ubuntu 20.04's default is /etc/php/{X.x}/{apache2|[others]}/php.ini) and ensure that session.use_cookies=1
Restart your server and then try to set the cookie. They should immediately be available.
You probably have sent header hereby making it impossible to set header for cookie.
It might be a simple solution of ob_start() at the start of your page.
[Solution tested in XAMPP for PHP 8.0.19]
I modified the file php.ini and set session.auto_start=1. Keep in mind that i'm calling session_set_cookie_params([param => value]) just before session_start() every time this functions appears in my code, in every file.
session.auto_star: Initialize session on request startup.
http://php.net/session.auto-start
Still studying and analysing the reason and functionality of this, it was kind of a serendipity.
Probably not the most secure solution.
You can't get the $_COOKIE on the same request but you can get $_SESSION on the same request.
So the idea is
Set the $username in both the session & cookie.
Get the username from the session for the first time (if the same request)
Unset session
Always get the cookie from $_COOKIE from next request.
// Set Cookie
setcookie('username',$username,time()+60*60*24*365);
$_SESSION['username'] = $username;
//GET Cookies
if(!$_COOKIE['username']){
$username = $_SESSION['username'];
unset($_SESSION['username']);
}else{
$username = $_COOKIE['username'];
}

New cookie value not taken into account without refreshing page [duplicate]

I have the following PHP function:
function validateUser($username){
session_regenerate_id ();
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
setcookie('username2',$username,time()+60*60*24*365);
header("Location: ../new.php");
}
And then I fetch the cookie:
echo $_COOKIE['username2']; exit();
(I only put exit() for debugging purposes)
Only problem, it's coming out blank. Any ideas?
UPDATE:
This is how the function is called:
if(mysql_num_rows($queryreg) != 0){
$row = mysql_fetch_array($queryreg,MYSQL_ASSOC);
$hash = hash('sha256', $row['salt'] . hash('sha256', $password));
if($hash == $row['password']) {
if($row['confirm'] == 1){
if(isset($remember)){
setcookie('username',$username,time()+60*60*24*365);
setcookie('password',$password,time()+60*60*24*365);
} else {
setcookie('username','',time()-3600);
setcookie('password','',time()-3600);
}
validateUser($username);
I didn't include all the if() statements to save some space.
try adding the path = /, so that the cookie works for the whole site not just the current directory (that has caught me out before)
example
setcookie('password',$password,time()+60*60*24*365, '/');
also make sure the cookie is the first thing being output
as advised in the php manual (this has caught me out before too)
Like other headers, cookies must be sent before any output from your
script (this is a protocol restriction).
Why you are having this problem
The problem comes from the fact that setcookie() doesn't set the cookies immediately, it sends the headers so the browser sets the cookies. This means that, for the current page load, setcookie() will no generate any $_COOKIE.
When the browser later on requests a page, it sends the cookies in the headers so the PHP can retrieve them in the form of $_COOKIE.
Simple, old solution
About solutions, the obvious one:
setcookie('username',$username,time()+60*60*24*365);
// 'Force' the cookie to exists
$_COOKIE['username'] = $username;
A better solution
I created a class, Cookie, that addresses the problems that setcookie() and $_COOKIE share:
// Class that abstracts both the $_COOKIE and setcookie()
class Cookie
{
// The array that stores the cookie
protected $data = array();
// Expiration time from now
protected $expire;
// Domain for the website
protected $domain;
// Default expiration is 28 days (28 * 3600 * 24 = 2419200).
// Parameters:
// $cookie: $_COOKIE variable
// $expire: expiration time for the cookie in seconds
// $domain: domain for the application `example.com`, `test.com`
public function __construct($cookie, $expire = 2419200, $domain = null)
{
// Set up the data of this cookie
$this->data = $cookie;
$this->expire = $expire;
if ($domain)
$this->domain = $domain;
else
{
$this->domain =
isset($_SERVER['HTTP_X_FORWARDED_HOST']) ?
$_SERVER['HTTP_X_FORWARDED_HOST'] :
isset($_SERVER['HTTP_HOST']) ?
$_SERVER['HTTP_HOST'] :
$_SERVER['SERVER_NAME'];
}
}
public function __get($name)
{
return (isset($this->data[$name])) ?
$this->data[$name] :
"";
}
public function __set($name, $value = null)
{
// Check whether the headers are already sent or not
if (headers_sent())
throw new Exception("Can't change cookie " . $name . " after sending headers.");
// Delete the cookie
if (!$value)
{
setcookie($name, null, time() - 10, '/', '.' . $this->domain, false, true);
unset($this->data[$name]);
unset($_COOKIE[$name]);
}
else
{
// Set the actual cookie
setcookie($name, $value, time() + $this->expire, '/', $this->domain, false, true);
$this->data[$name] = $value;
$_COOKIE[$name] = $value;
}
}
}
Then you can use it like this:
$Cookie = new Cookie($_COOKIE);
$User = $Cookie->user;
$LastVisit = $Cookie->last;
$Cookie->last = time();
And of course, you have to pass it around. Much better than having globals.
Here is the general syntax of setcookie
setcookie(name,value,expire,path,domain,secure);
Look at third argument, if you do not set it the script will take it to current working directory. So if you set a cookie without setting path at a.com/b/setcookie.php the cookie will not be available to a.com/checkcookie.php. What you are doing is setting cookie in a subfolder and the redirecting to a parent folder, look at ../, where it is not available hence the issue. How to avoid this? Normal procedure is to supply a path that is /, in your case supply / as fourth param. The fifth argument for your cookie will set it secure. http://www.php.net/setcookie has more explanation. This should fix your problem. Setting domain path to domain.com, will make the cookie available to everything under domain.com but not to something.domain.com. Set domain value to .domain.com, look at the dot preceding domain.com, will make it available across anything.domain.com. HTH!
Thought I would add another possible reason why a cookie may not be either setting or showing random functional behavior.
The following case may be applicable to some programmers having what appears to be an illusive cookie setting issue as a result of the incorrect usage of header_remove()
If you try to set a cookie before calling header_remove(), the cookie will never be created because you have also immediately destroyed the header that was set in order to create the cookie before it was buffered out to the client.
You may find when fiddling around that your cookie suddenly works for an unknown reason, so you need to understand the race-conditions around headers:
On first run you set a cookie and don't call header_remove() at all.
On a second run you do call header_remove()
You will find your cookie is now always set regardless of condition (2) and the number of times it is called because (1) happened first at least once.
The cookie will remain set until it either expires, is overwritten or unset()
The same will apply when modifying headers like a cookie value before the eventual call of header_remove(), you again will fail to set new values because they will be wiped before the response is buffered out to the user.
You need to set cookies and any other headers for that matter after a header_remove() not before.
Use header_remove() to cleanup ALL previously set headers in order to set new headers for a final output.
An example of scenario for such a case may be as follows:
Use header_remove() to alter a hierarchy of HTTP Response codes for a RESTFUL API where you are using axios with interceptors.
Your application sets a 400+ header error first, should the application error out at any point of execution.
Modify the header to a 200 when final desired execution point has been reached & a valid response is expected.
In such an event, it is likely you want to preserve all other previously set headers but clear out the HTTP Status (400?) code in order to set a new (200?) code for the final response.
If you try to set the header again in order to change the status code before removing the previously set header then you will get the "Headers already sent" error.
You can remove specific headers with header_remove, here is how to unset the status code and set a new code in stages:
// Set a default status code
http_response_code(500);
// Boot Logic runs - if fails here 500 is returned
// Authentication Logic - If unauthorized ?
header_remove('HTTP/1.0'); // Clear previous 500
http_response_code(401); // Set new status code
// else ?
// Return Data Logic - Success
header_remove('HTTP/1.0'); // Clear previous 500
http_response_code(200) // Set new status code
This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
this is how the structure looks
<?php
$cookie_name = "user";
$cookie_value = "Ahmed Moftah";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
?>
<?php
if(!isset($_COOKIE[$cookie_name])) {
echo "Cookie named '" . $cookie_name . "' is not set!";
} else {
echo "Cookie '" . $cookie_name . "' is set!<br>";
echo "Value is: " . $_COOKIE[$cookie_name];
}
?>
<html>
<body>
</body>
</html>
It might be a cache problem. Try closing the browser and opening a new one with the localhost file path. I had the same issue and my page was cached so the cookies weren't working, even though I could put in new code and see a change on the page. Very weird... Cleaning your cache might help, try that first. Then try a new browser, then try to go to your localhost:8080 index and hit refresh to see when the last page was modified.
If that doesn't fix it, try restarting LAAMP or XAAMP or whatever you are using.
This happens with the session cookies are disabled.
You can navigate to your php.ini file(changes depending on server. Ubuntu 20.04's default is /etc/php/{X.x}/{apache2|[others]}/php.ini) and ensure that session.use_cookies=1
Restart your server and then try to set the cookie. They should immediately be available.
You probably have sent header hereby making it impossible to set header for cookie.
It might be a simple solution of ob_start() at the start of your page.
[Solution tested in XAMPP for PHP 8.0.19]
I modified the file php.ini and set session.auto_start=1. Keep in mind that i'm calling session_set_cookie_params([param => value]) just before session_start() every time this functions appears in my code, in every file.
session.auto_star: Initialize session on request startup.
http://php.net/session.auto-start
Still studying and analysing the reason and functionality of this, it was kind of a serendipity.
Probably not the most secure solution.
You can't get the $_COOKIE on the same request but you can get $_SESSION on the same request.
So the idea is
Set the $username in both the session & cookie.
Get the username from the session for the first time (if the same request)
Unset session
Always get the cookie from $_COOKIE from next request.
// Set Cookie
setcookie('username',$username,time()+60*60*24*365);
$_SESSION['username'] = $username;
//GET Cookies
if(!$_COOKIE['username']){
$username = $_SESSION['username'];
unset($_SESSION['username']);
}else{
$username = $_COOKIE['username'];
}

Check if a PHP cookie exists and if not set its value

I am working on a multilingual site so I tried this approach:
echo $_COOKIE["lg"];
if (!isset($_COOKIE["lg"]))
setcookie("lg", "ro");
echo $_COOKIE["lg"];
The idea is that if the client doesn't have an lg cookie (it is, therefore, the first time they've visited this site) then set a cookie lg = ro for that user.
Everything works fine except that if I enter this page for the first time, the first and second echo return nothing. Only if I refresh the page is the cookie set and then both echo print the "ro" string I am expecting.
How can I set this cookie in order to see its value from the second echo on the first visit/page load of the user? Should be without needing to refresh the page or create a redirect.
Answer
You can't according to the PHP manual:
Once the cookies have been set, they can be accessed on the next page
load with the $_COOKIE or $HTTP_COOKIE_VARS arrays.
This is because cookies are sent in response headers to the browser and the browser must then send them back with the next request. This is why they are only available on the second page load.
Work around
But you can work around it by also setting $_COOKIE when you call setcookie():
if(!isset($_COOKIE['lg'])) {
setcookie('lg', 'ro');
$_COOKIE['lg'] = 'ro';
}
echo $_COOKIE['lg'];
Cookies are only sent at the time of the request, and therefore cannot be retrieved as soon as it is assigned (only available after reloading).
Once the cookies have been set, they can be accessed on the next page load with the $_COOKIE or $HTTP_COOKIE_VARS arrays.
If output exists prior to calling this function, setcookie() will fail and return FALSE. If setcookie() successfully runs, it will return TRUE. This does not indicate whether the user accepted the cookie.
Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires. Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);.
Source
If you set a cookie with php setcookie you can see the set and the value of the cookie, as an example, with the developer tools of firefox just in time.
But you need to reload/load the same/next page if you wanna read, get or check the cookie and the value inside to work with that cookie in PHP.
With this example you can choose if you wanna reload the same page with PHP, HTML or JAVASCRIPT.
If the cookie is not accepted or cookies are disabled, a loading loop is obtained and the browser stops loading the page.
LONGVERSION WITH PHP 'header' RELOAD SAME PAGE:
<?php
$COOKIE_SET = [
'expires' => '0'
,'path' => '/'
// ,'domain' => 'DOMAIN'
,'secure' => 'true'
,'httponly' => 'true'
// ,'samesite' => 'Strict'
];
$COOKIE_NAME = "MYCOOKIE";
$COOKIE_VALUE = "STACKOVERFLOW";
if(!isset($_COOKIE[$COOKIE_NAME])){
setcookie($COOKIE_NAME, $COOKIE_VALUE, $COOKIE_SET);
// YOU NEED TO RELOAD THE PAGE ONCE
// WITH PHP, HTML, OR JAVASCRIPT
// UNCOMMENT YOUR CHOICE
// echo '<meta http-equiv="refresh" content="0;URL=/">';
// echo '<script>window.location.replace("/");</script>';
header("Location: /");
exit;
}
else{
echo ($_COOKIE[$COOKIE_NAME]);
}
?>
SHORTVERSION WITH PHP 'header' RELOAD SAME PAGE:
if(!isset($_COOKIE['MYCOOKIE'])){
setcookie('MYCOOKIE', 'STACKOVERFLOW');
header("Location: /");
exit;
}
echo ($_COOKIE['MYCOOKIE']);

Cookies cannot be set the first time after clearing history in Firefox

I am trying to setup a session management with cookies in PHP.
My code is as follows:
if(empty($_COOKIE )) {
setcookie('session_id', md5(uniqid()), time()+(EXPIRE CONSTANT));
}
$session_id = isset($_COOKIE['session_id']) ? $_COOKIE['session_id'] : 0;
I will then check session_id for 0 and print an error message if cookies are disabled.
This works fine if cookies are really disabled.
The problem is, if a user clears his history the first time he visits
the site he will get the error message even if cookies are enabled.
Anyone have any clues about this ?
Thank you in advance
When you do the setcookie call, the cookies will be sent when the header is output to the browser. This means the cookie won't be available until the next page load (when the client sends the cookie back to the server). This is mentioned in the php manual for setcookie http://php.net/manual/en/function.setcookie.php:
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
Once the cookies have been set, they can be accessed on the next page load with the $_COOKIE or $HTTP_COOKIE_VARS arrays. Note, superglobals such as $_COOKIE became available in PHP 4.1.0. Cookie values also exist in $_REQUEST.
You won't be able to determine if cookies are enabled/disabled until the page has reloaded (from php). I think you'll have to do this check with javascript, or to stay in php do a redirect after setting the cookie for the first time, something like:
if(empty($_COOKIE)) {
if (isset($_GET['cookieset'])) {
// do error message, cookie should be set
}
setcookie('session_id', md5(uniqid()), time()+(EXPIRE CONSTANT));
header('location: http://mysite.com/index.php?cookieset=1');
exit;
}
$session_id = isset($_COOKIE['session_id']) ? $_COOKIE['session_id'] : 0;
#bencoder : I have done the test on iPad and Chrome/PC : you are right for iPad, you do need to refresh the page before you can read the cookie data, but on Chrome/PC, after deleting all cookies, if you set a new one from PHP, you can perfectly get the values directly on the first page load. Why ? There must be a more precise explanation. Why two different behaviors? Does the order of this output/availability of the data depend on the browser request to the server? Interesting to know...

Cookie won't unset

OK, I'm stumped, and have been staring at this for hours.
I'm setting a cookie at /access/login.php with the following code:
setcookie('username', $username, time() + 604800, '/');
When I try to logout, which is located at /access/logout.php (and rewritten to /access/logout), the cookie won't seem to unset. I've tried the following:
setcookie('username', false, time()-3600, '/');
setcookie('username', '', time()-3600, '/');
setcookie('username', '', 1, '/');
I've also tried to directly hit /access/logout.php, but it's not working.
Nothing shows up in the php logs.
Any suggestions? I'm not sure if I'm missing something, or what's going on, but it's been hours of staring at this code and trying to debug.
How are you determining if it unset? Keep in mind that setcookie() won't remove it from the $_COOKIE superglobal of the current script, so if you call setcookie() to unset it and then immediatly print_r($_COOKIE);, it will still show up until you refresh the page.
Try pasting javascript:alert(document.cookie); in your browser to verify you don't have multiple cookies saved. Clear all cookies for the domain you're working on to make to sure you're starting fresh. Also ini_set(E_ALL); to make sure you're not missing any notices.
Seems to be a server issue. My last domain was pretty relaxed on PHP error handling while the new domain shows every error. I'm using both sites side by side and the old one removes the cookie as it should.
Is there perhaps a timezone issue here? Have you tried setting using something farther in the past, like time() - (3600*24)? PHP's documentation says that the internal implementation for deleting cookies uses a timestamp of one year in the past.
Also, you should be able to use just setcookie('username', false); without passing an expiration timestamp, since that argument is optional. Maybe including it is confusing PHP somehow?
How you use cookies data in your application?
If you read the cookies and check if username is not false or not '', then setting it to false or '' will be sufficient, since your application will ignore the cookies value.
You better put some security in cookies value, to prevent user change it's value. You can take a look of CodeIgniter session library, see how CI protect the cookies value using hash. Unauthorized value change will detected and the cookies will be deleted.
Also, CI do this to kill the cookies:
// Kill the cookie
setcookie(
$this->cookie_name,
addslashes(serialize(array())),
(time() - 31500000),
$this->cookie_path,
$this->cookie_domain,
0
);
You can delete cookies from javascript as well. Check here http://www.php.net/manual/en/function.setcookie.php#96599
A simple and convenient way, is to use this additional functions:
function getCookie($name) {
if (!isset($_COOKIE[$name])) return false;
if ($_COOKIE[$name]=='null') $_COOKIE[$name]=false;
return $_COOKIE[$name];
}
function removeCookie($name) {
unset($_COOKIE[$name]);
setcookie($name, "null");
}
removing a cookie is simple:
removeCookie('MyCookie');
....
echo getCookie('MyCookie');
I had a similar issue.
I found that, for whatever reason, echoing something out of logout.php made it actually delete the cookie:
echo '{}';
setcookie('username', '', time()-3600, '/');
I had the same issue; I log out (and I'm logged out), manually reload the index.php and then I'm logged in again. Then when I log out, I'm properly logged out.
The log out is a simple link (index.php?task=logout). The task removes the user from the session, and "deletes" (set value '' and set expiry in the past) the cookie, but index.php will read the user's auth token from the cookie just after this (or all) task (as with normal operations). Which will reload the user. After the page is loaded the browser will show no cookie for the auth token. So I suspect the cookie gets written after page finish loading.
My simple solution was to not read the cookie if the task was set to logout.
use sessions for authentication, don't use raw cookies
http://www.php.net/manual/en/book.session.php

Categories