I'm working on a simple cookie notice that appears on first visit only and again but only until 30 days has gone by.
The problem that I'm having is the page that is setting the cookie for the entire domain keeps receiving the notice once I go to a different page and then back again, unless I do a hard refresh (CTRL+F5) the notice just won't go away.
In my header.php I have:
$value = 'first_visit';
setcookie("visitor", $value);
setcookie("visitor", $value, time()+604800);
setcookie("visitor", $value, time()+604800, "/", ".example.com");
if(isset($_COOKIE['visitor']) && ($_COOKIE['visitor'] == true)){
// do nothing
} else {
echo '<div id="cookie">By continuing to use our Site, you are agreeing to the placement of cookies on your computer by us and our third party service providers.</div>';
}
So the idea of the code is that the user visits the site and then the page triggers a creation of a cookie, the value of this cookie is not important since the code will simply check to see if one exists, the first time the visitor visits the site, it does not exist therefore they it echo's else, going to other pages other than the page I just visited does // nothing as intended but if I go back to the page that triggered the creation, its still else, unless I do a hard page refresh.
I have also tried:
<?php
if(isset($_COOKIE['visitor']) && ($_COOKIE['visitor'] == true)){
// DO NOTHING
} else {
$value = 'first_visit';
setcookie("visitor", $value, time()+604800, "/");
echo '<div id="cookie">By continuing to use our Site, you are agreeing to the placement of cookies on your computer by us and our third party service providers</div>';
}
?>
I don't think there's anything wrong with your code - ie it's working as expected based on the code. I just don't think you see what the code is actually doing. You say the cookie is eventually set, but you are setting the cookie on a page, moving on, then using back button and getting to a page with that message again. This is likely browser cache, and likely confirmed as you say a hard refresh fixes this.
It seems odd the way you are doing all of this. All I can get from your question and code is you require:
First visit - user sees message and cookie is set
Consequent visits/pages after this - user doesn't see message because cookie is set
The only way you can avoid the browser back messing this up for you is to do a redirect after you set the cookie (eg $_SERVER['PHP_SELF']). but then you can't use the same file to show the message as by then the cookie will be set.
You should rethink this and handle the whole thing differently, but as it stands, with the code you have presented, all I can suggest setting a session.
header.php
session_start();
if (!isset($_COOKIE['visitor']) || ($_COOKIE['visitor'] != true)) {
$value = 'first_visit';
setcookie("visitor", $value, time() + 604800, "/", ".example.com");
$SESSION['displayMessage'] = true;
} else {
if (isset($SESSION['displayMessage'])) {
unset($SESSION['displayMessage']);
}
}
if (isset($SESSION['displayMessage'])) {
echo '<div id="cookie">By continuing to use our Site, you are agreeing to the placement of cookies on your computer by us and our third party service providers.</div>';
}
On the first visit the cookie won't be set so it's set and a session is set, as the session is set it'll show the message. Then on any other page load as the cookie is set the ELSE will kick in and session is unset, and therefore the message is not shown.
(I reverted your cookie checks so you don't have that awful pointless // do nothing ;) )
The above code is very clunky, and I cried a bit writing it. Again, I advise you step back and rethink how you are handling all of this to make it more robust. Separate out your requirements into different files, better use functions, and then call things as and when you need them based on other things being set :)
Related
I dont really have much experience in cache controlling and CakePhp. I am not a regular programmer as well. I got a situation where if the user is visiting a site for a first time there will be a pop up appearing on the screen. If the user visited it before there wont be any popup.
As for checking the user is authentic, i can use
<?php if (empty($auth_user)) { ?>
//codes for popup modal
<?php } ?>
My question is, is that possible to implement some logic like this to catch the cache or check wheather the tmp file is empty or not?
No there is not good ways to catch cache, But there only one way COOKIES to do it but it will be terminated and work newly as user just delete them in his browser.
As php is an server side scripting language
If you not want to save cookie then use LOCALSTORAGE but in JAVASCRIPT
1.COOKIE(Cookies can be stored via PHP)
setcookie(nameOfCookie, valueOfCookie, expireTimeOfCookie, pathOfCookie);
Simple insert "/" in pathOfCookie
Getting COOKIE in PHP
<?php
if(isset($_COOKIE[$nameOfCookie])) {
//User already visited your site.
} else {
//Use doesn't visited your site yet.
//Show POPUP here. And set cookie here (In Else Condition).
}
?>
Keep in mind that if the expiryTimeOfCookie passes it will expiry. And not exist (Time In Seconds For 1 Day = 86400
I have a page, login.php, that processes a username and password and if successful it sets session variables and then redirects the user to home.php. The relevant part of login.php is here:
if ($pwdHash == $storedpass) {
$success = true;
$sessionStatus = session_status();
if ($sessionStatus !== PHP_SESSION_ACTIVE) {
session_start();
}
$_SESSION['user_id'] = $user;
$_SESSION['logged_in'] = true;
session_write_close();
header('Location: http://www.examplesite.com/home.php');
header("HTTP/1.1 303 See Other");
die("redirecting");
}
Then home.php tries to collect the session variable
$sessionStatus = session_status();
if ($sessionStatus !== PHP_SESSION_ACTIVE) {
session_start();
}
$loggedIn = $_SESSION['logged_in'];
The problem is that on the first login attempt, $_SESSION['logged_in'] is undefined and generates an error, even though login.php was successful.
Notice: Undefined index: logged_in
A var_dump of $_SESSION returns an empty array, but sessionStatus reports that the session was already started, it did not have to execute session_start.
This forces the user to log in a second time, then everything is fine. So is the redirect just happening too fast for the session variable to get set? Should I put a delay in the redirect? (and how would I do that?) Or is this something else that I'm doing wrong?
EDIT: I've checked with my host based on an answer to a similar question and confirmed that a session would never be served by more than one server and there is no need to enable sticky sessions or anything like that. I've also updated the code above based an answer offered below and some other research but the error persists.
The session is probably automatically saved when the script ends. You redirect before the script ends.
How long your script takes to really end depends very much on what other code needs to wind down. It is better to explicitly save the session.
How to do this depends on what kind of sessions you use. One type can be closed like this:
http://php.net/manual/en/function.session-write-close.php
If that's the one you're using do this:
if ($pwdHash == $storedpass) {
$success = true;
$_SESSION['user_id'] = $user;
$_SESSION['logged_in'] = true;
session_write_close();
header('Location: http://www.examplesite.com/home.php');
header("HTTP/1.1 303 See Other");
die("redirecting");
}
And the session should be available to the next page when you redirect.
If your sessions work differently, you have to adapt the code, of course. The point I'm trying to make is: Never put a delay in your code. It's unreliable, and pointless. Simply save the session before you redirect.
I have experienced the same issue while writing the session content to the database.
To make it work I have added the sleep() function before setting the session variable, just like below.
sleep(2);
$_SESSION['GUID'] = uniqid(time().rand());
It resolves the issue for me.
We have observed this issue when the page hits are frequent but if one or two users are accessing the page it works as expected.
I have encountered this same issue with a login page but none of the suggestions work for me. The only thing I've found that does work is redirecting the page to itself after 1 second and then checking the session variables to see if the login was successful...
startSession(); // assigns all the login session variables, etc.
header('Refresh: 1; URL=/[THIS_PAGE].php'); // [THIS_PAGE] = the current login page
However, this is a very inelegant solution and I don't like using it. But it "works".
This problem persists. In my case, the user login goes without a problem to the protected homepage, but clicking on a menu link causes the user to be dumped back to the login page to login again. A check on certain Session values (required for both pages) shows these are not set on going to the specific menu link (while other menu links cause no problem). The code requiring a session value is the same in all cases. Not all users experience the problem. Seems that those with less robust connections to the internet always experience this problem. Others, never.
I am attempting to set a cookie and then check to see if the cookie has been set.
So in one function, I have it make the cookies:
public function makeCookies(){
Cookie::queue('logged_in', $value, 15);
Cookie::queue('user_id', 2);
//return Response::make()->withCookie(Cookie::make('logged_in', $value, 15))->withCookie(Cookie::forever('user_id', 2));
}
And in the other function, I try to check to see if the cookie has been set:
public function checkCookies(){
$this->makeCookies();
if(Cookie::get('logged_in') && Cookie::get('user_id')){
return 'Logged In!';
}
}
However the only way this works is if I add 'return' before $this->makeCookies(); However, I want to be able to get to the conditional below it. Is there any way I can go about doing this? Any help is greatly appreciated.
To understand the Cookie Creation/Read process:
The user's browser sends a request for a page, along with any cookies that it currently has for the site
The site serves up the page, and any cookies you create become a header in your response.
Subsequent requests to your site will send the cookies created in #2.
What you are asking...to be able to read cookies that you create in step #2 in step #1...not possible.
Now, depending on how the Cookie class is created, you could make it so that when the Cookie::queue() is called, that it creates in-memory data that reflects what the cookie "should be" on the next request, but it doesn't truly know whether or not the user's browser will accept cookies, etc.
This is why many sites, after creating a cookie give the user a redirect to a page with something like ?checkCookie=1. This way, on the subsequent request, they can verify that your browser supports cookies...and if the cookie doesn't exist on the ?checkCookie page, they give you an error saying that their site requires cookie support. However, it does require a second round to the server to read cookies from the browser that were created.
UPDATE 2015-04-24 Per #Scopey, Laravel does support in-memory retrieval of cookies via queued(). So, you should be able to do:
public function checkCookies(){
$this->makeCookies();
$loggedIn = Cookie::get('logged_in') ?: Cookie::queued('logged_in');
$userId = Cookie::get('user_id') ?: Cookie::queued('user_id');
if( $loggedIn && $userId ){
return 'Logged In!';
}
}
SECURITY CONCERNS (NOT DIRECTLY ANSWERING THE QUESTION)
Your question was only about the cookies, so that's all I answered. However, now that I'm looking at your code, I feel I would be remiss not to point this out for anyone that happens to be reading this. This may just be a "how to" for yourself and not production code, but that code could be very dangerous if it ever went public.
Make sure you do NOT TRUST a user_id stored in a cookie to determine what user is coming in via cookies. If you rely on that, and I come to your site, I can modify my cookie to any user_id I want and get into other people's accounts.
General Safety Rules:
A cookie should contain a GUID, or similar random string to identify the session. This random string should be sufficiently long (e.g. 32 characters or greater, IMHO) that it is not easy for someone to brute-force their way to hijacking sessions.
The user_id should be stored in the $_SESSION (or laravel's wrapper for session if applicable) so that the user doesn't have any access to the user_id to be able to modify it.
In plain PHP, this something like this for the login page:
session_start();
if( isValidPassword($_POST['username'], $_POST['password']) ) {
$_SESSION['user_id'] = $user->Id;
}
else {
die('invalid login credentials');
}
The session_start() method automatically generates a cookie for the user with that long, random string (so you don't even have to worry about that part.)
On subsequent pages, you just check the session user_id to know who is logged in:
session_start();
if( empty($_SESSION['user_id']) ) {
die('You are not logged in and cannot access this page');
}
Change as needed per Laravel's documentation, which if they have their own session wrapper, I'm sure is well documented on best practices.
Excellent description by #KevinNelson about cookies but Laravel does support fetching back any cookies you have queued in the current request. Try using
Cookie::queued('logged_in');
The catch is, the cookie will only be "queued" during the request that you queued it. You will have to use get like you are for any other requests.
I have a section of a website that sets a session variable. On another section of the site, if that variable is set, then it redirects them back to where the part of the site that set the variable.
<?php
//page1:
session_start();
$_SESSION['pg1']=true;
//page2
if ($_SESSION['pg1']===true)
{
header('Location: http://www.mysite.com/?page=1&WELCOME_BACK');
}
?>
I think this behaves like I want by defalut, but I want Googlebot to be able to visit page1, then visit page2 without being re-directed. Can anyone confirm that?
What I mean is, does a visit from Googlebot (or other SEs in general) generate a session that persists between pageviews.
(I know, if someone closes their browser they can come back to page2, but it's okay if they do that.)
Googlebot does not accept cookies from strangers, so there will be no session variables when it visits your second page. This will result in what you want to happen here, but keep it also in mind for future reference.
if ($_SESSION['pg1'] == true && strpos($_SERVER['HTTP_USER_AGENT'],'Googlebot') === false)
{
}
List of user agent strings: http://www.useragentstring.com/pages/useragentstring.php
if(isset($_POST['remember'])) {
if(!isset($_COOKIE['tracker_id'])) {
setcookie('tracker_id', $_SESSION['id'], time()+2592000);
setcookie('tracker_username', $_SESSION['username'], time()+2592000);
setcookie('tracker_rsn', $_SESSION['rsn'], time()+2592000);
}
}
I know the code works, because I check to see if there are cookies before I log in, and there aren't. I log in, and there are cookies. I close the tab (not the browser), re-open it in a new tab, and the cookies aren't there. I'm not sure if I overlooked something, but I'm not quite sure what's up here...
Any help is appreciated
How are you checking to see if the cookies are there or not? Checking cookies array doesn't tell you the whole story. If you don't already have it, download the Web Developer Addon for FireFox. It has a feature to view, edit, and delete cookies for the site you are on. View your cookies after logging in. That will give you insight as to what is actually being set by the browser. Then close the browser and open again, visit site, and view the cookies again. See if they are perhaps still there, and just not being read.
I've learned the hard way that it's a really good idea to set the cookie path and domain explicitly rather than letting PHP default it. Otherwise cookies from mydomain.com will have a different path than www.mydomain.com and that can lead to the www cookies not being read from mydomain.com and other fun stuff. We now always explicitly set our cookies, after wasting probably a week's worth of development time over the course of 6 months trying to track that issue down.
If paths aren't the issue you might be inadvertently deleting the cookies. Do the values you are passing in from the SESSION always exist for sure when that code is run? A false value tells PHP to delete a cookie, which could happen by accident if the values are not defined in the array and you don't have a strong error reporting level.
Your code should work as you describe provided that:
1) there is nothing else serverside interfering with the values of the cookies
2) you haven't told your browser to treat all cookies as session cookies
Have you built a test rig with just the minimum code necessary to set and read the cookies? Fromt the snippet you posted, there's obviously a lot more going on in your code. And try to test it in different browsers.
Something like:
<?php
if ($_GET['set') {
setcookie('tracker_id', 'tracker_id set at ' . date('r'), time()+2592000);
setcookie('tracker_username', 'tracker_username set at ' . date('r'), time()+2592000);
setcookie('tracker_rsn', 'tracker_rsn set at ' . date('r'), time()+2592000);
}
print_r($_COOKIE);
?>
C.