Cookies arent being set in my first view.
Is this how it should be ? or am I mistaken
Please view the code below for further illustration:
if( !get_cookie('rate') ){
$cookie_rate = array(
'name' => 'rate',
'value' => '10',
'expire' => '100000'
);
set_cookie($cookie_rate);
}
var_dump( get_cookie('rate') ); //returns ( boolean false )
if( !isset($_COOKIE['foo']) ){
$_COOKIE['foo'] = 'bar';
}
var_dump( $_COOKIE['foo'] ); // This yields string 'bar' (length=3) on the first visit
Doing the same thing with php cookies yeilds an array with cookie values.
This problem persists only in the first visit of a page.
This isn't a CodeIgniter vs PHP issue. You just don't understand how cookies work.
Cookies are a header sent by the server which the browser must send back on subsequent requests. $this->input->set_cookie() and set_cookie() send a cookie header.
$_COOKIES on PHP (and thus $this->input->cookie() and therefore the get_cookie() helper) only contain cookies which the browser sent.
Thus when you set a cookie with set_cookie(), you won't be able to get_cookie() until the browser's next request.
Seeing as CI's set_cookie probably utilizes the same mechanism as PHP's setcookie(), this entry from the manual probably applies:
Common pitfalls
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);.
I can't see any mention of this behaviour in the CI manual, but it's likely to be the same thing.
If I understood this right youre trying to see the data of the cookie before reloading the page which won't work. Try setting the cookie, reloading the page and then checking the cookie for data.
Also sometimes you need to specify domain and such, perhaps it doesn't apply right now but it might be nice to know later if they suddenly stop working, from CI-documentation:
$cookie = array(
'name' => 'The Cookie Name',
'value' => 'The Value',
'expire' => '86500',
'domain' => '.some-domain.com',
'path' => '/',
'prefix' => 'myprefix_',
'secure' => TRUE
);
$this->input->set_cookie($cookie);
Also, consider using the session class instead of cookies if you don't need anything specifically from cookies since they are more secure. http://codeigniter.com/user_guide/libraries/sessions.html
Thats probably not the problem, in fact thats how cookie works, its set and on next page load it seems to be visible from then.
Related
Brief Summary
When I click a link from gmail, the cookies and sessions are lost. But if I copy the link in gmail and paste it in a blank tab, the cookies are retained!
Long Detail
At www.mydomain.com, i set cookies and PHP session with following options:
$myCookieSessionOptions = array(
'lifetime' => (time() + 60*60*24*363),
'path' => "/",
'domain' => "." . "mydomain.com",
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
);
session_set_cookie_params ( $myCookieSessionOptions ) ;
session_name("mySessionName");
session_start();
The above is the code both on page login.php and anotherpage.php.
On login.php when I login and set sessions, etc. the session_id() shows up as c7a9c180b767e889ad0161dc613aec41, for example.
When i access anotherpage.php in a blank tab and with some GET parameters (and my code does nothing to the session), i get the same session_id().
However, when the same link for anotherpage.php (along with the get parameters) is sent in an email, then I get a totally new session_id: 3fc7f8749ba6eb46ddd35a0db3a17589 for example.
And in the other tab, which had login.php, the session is lost, as a new session is created, obviously.
The question is if this behaviour is normal?? And this is not with gmail alone, obviously. From "anyotherdomain.com", when i click on a link to my domain, no cookies are sent!
Very weird! Is there any documentation on this behavior?
Any help will be appreciated
session auto start is Off. Checked in phpinfo
And there's no code before the above that does anything at all with the sessions
Thanks
Rajan
I figured it out! If I have samesite="none", the problem disappears
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
And tested it & it works fine.
As per the doc:
Strict
Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
Okay so I've created a login system using PHP Sessions which stores user-related data within $_SESSION while logged in. To reach a PHP $_SESSION / session cookie whose expiry gets extended by x seconds every time the client refreshes a page, I created the following callback, which I call upon every page initiation:
<?php
if ( session_status() === PHP_SESSION_NONE ) {
session_start(
[
'cookie_path' => '/',
'cookie_domain' => 'mydomain.com',
'cookie_secure' => true,
'cookie_httponly' => true,
'cookie_samesite' => 'Strict',
'use_strict_mode' => true,
'use_trans_sid' => false,
'use_only_cookies' => true
]
);
} else {
// If session already exists, simply take it up again without overwriting parameters
session_start();
}
// Then determine the lifetime of the cookie (was only able to make the session cookie
// lifetime expendable using this syntax, as explained in the [first example of the php docs](https://www.php.net/manual/de/function.session-set-cookie-params.php)
setcookie(
session_name(),
session_id(),
[
'expires' => time() + x,
'path' => '/',
'domain' => 'mydomain.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]
);
?>
The reason why I specify all the:
httponly
secure
cookie path
cookie domain
samesite
parameters upon the very first call of session_start() AND also in the call of setcookie() is because if I specify one of them in session_start() and not in setcookie() or vice-versa, the browser returns two session cookies with the same session IDs, one having all of the mentioned flags, and the other without:
Now the problem is that, when I logout via the following callback, which I call as specified in the docs:
<?php
// Called via PHP Form Submit
session_start();
setcookie(
session_name(),
'',
time() - 42000,
'/',
'mydomain.com',
true,
true
);
session_destroy();
header( 'Location: mydomain.com' );
?>
I get the same problem as described in the images above; two session cookies in my browser, and again one having all the flags set, the other not, and the one without the flags set having set its expiry to the session's end, and the other one with its expiry set in x seconds; all exactly as in the image.
What am I doing wrong?
UPDATE
Is it may better to actually set all of the session cookie parameters via the php.ini file, and handle the session cookie expiry via a timestamp within $_SESSION, done like in this example?? Just thinking of a way of making the provision of any parameters in session_start() + any calls to setcookie() obsolete..
So my question is basically:
What's actually the best way of using several PHP session cookie flags, combined with a session expiry which is limited to let's say 10 mins, which gets refreshed by 10 mins on every page load?
Wondering if someone can provide some clarification on why this is behaving how it is when using samesite in a php session cookie.
example.com has the following :
session_name('Example_Login');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_start();
test.com has the following form posting to example.com :
<form method="post" action="https://www.example.com/" target="_blank" autocomplete="off">
<input type="hidden" name="username" value="demo_user">
<input type="hidden" name="password" value="demo_password">
<input type="hidden" name="signin" value="signin">
<button type="submit" name="submit">Login</button>
</form>
example.com receives the post and with php I use the $_POST variables sent to validate the login credentials and log the user in. With those values being valid, the user is not logged into example.com though. If, I change the samesite parameter on example.com's session cookie to 'lax' the posted form works as expected.
I did read up on the samesite parameter before adding it and I did not see anything that stuck out to me where it would affect posts/gets. What am I missing here? I don't see how the samesite parameter has ANY affect on what I am doing here. I sent a post from another domain, retrieve the variables, and do some logic with php... what does the samesite parameter for the session cookie have to do with anything here?
UPDATE:
I did some debugging. The post variables are sent and received fine, session is created on example.com and creates lots of $_SESSION vars, etc. I narrowed down the problem to a redirect that happens after the username/password is validated in php. If the user/pass is correct and the account exists I store user information in $_SESSION then I call the following in php :
header("Location: /main.php");
exit();
The redirect happens and upon reaching main.php $_SESSION is empty. All of its variables are gone. I echo'ed it and it shows the following :
Array
(
[user] => Array
(
[session] => 1
)
)
I switch the samesite parameter to 'lax'. Run the exact same debugging and $_SESSION is full of my user information as expected which was put there before the redirect.
I also changed my redirect to absolute as header("Location: https://www.example.com/main.php"); to see if that had an affect, but the problem still remains.
So, my question now is... when using samesite='strict' in my session... why is the session emptied after a redirect to a page on the same domain?
UPDATE 2:
I changed the session save path to another location specifically to debug and see what happens. When it reaches example.com it creates the session file and the values I added into it are there. When it reaches example.com/main.php (the redirect) it creates a brand new session file as seen above. My session settings and start are in their own file which is required first thing on these pages :
session_name('Example_Login');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_start();
So with samesite='strict' the above creates a new session, but with samesite='lax' it uses the same session file from the previous page. What gives? I am seeing where things are going wrong, but not why it is happening or how to fix it.
UPDATE 3:
Created a very simple test to demonstrate what is happening and why. See answer below. One can argue with me all day justifying why this works how it does, but I think the logic happening here is flawed.
SameSite=Strict means the cookie will not be sent on cross-site requests which includes cross-site POST requests and redirects triggered from the cross-site POST request.
SameSite=Lax is the correct option for your session cookie here. Being able to use Strict here is not better or more secure, it is too restrictive for this use case.
I've boiled this entire thing down to a simple test.
example.com has two pages :
test1.php
<?php
//session name
session_name('Test');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_save_path($_SERVER['DOCUMENT_ROOT'].'/sessions');
session_start();
//session stuff
$_SESSION['sessiontest'] = 'worked';
//cookie stuff
setcookie('testing', 'worked', ['expires' => 0, 'path' => '/', 'domain' => 'example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
//redirect to the other page
header("Location: /test2.php");
exit();
?>
test2.php
<?php
//session name
session_name('Test');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_save_path($_SERVER['DOCUMENT_ROOT'].'/sessions');
session_start();
echo '<pre>'.print_r($_SESSION,1).'</pre>';
echo '<pre>'.print_r($_COOKIE,1).'</pre>';
?>
test.com
go to test
If you start at test.com the session and cookie (created at example.com/test1.php) are empty at example.com/test2.php. This all has to do with the chaining and logic being used for samesite which in my opinion is flawed in this case. The session and cookie it is preventing are being CREATED on the site this is supposed to protect from the 'outside'. I'm sure someone will have some argument justifying this, but as far as I see it this whole thing was created to mitigate the results of bad coding... and in this case... is preventing legitimate code from working as it should. This example shows I am not 'using' anything from test.com... yet because of the redirect happening when you reach example.com/test1.php it sees the session and cookie created on it as more or less 'bad' when reaching example.com/test2.php because the chain started at test.com.
I am writing a cookie for auto login users.
It works almost flaw less. But when the Session times out the cookie gets deleted, although it's set for 30 days.
I can't understand why this is happening.
If I close the browser and reopen it, all are fine, but if I leave the browser open and let the Session time out the cookie gets deleted to.
Configure::write('Session', array(
'defaults' => 'php',
'cookie' => 'KPD',
'timeout' => 180,
'cookieTimeout' => 30 * 1440
));
UPDATE: I found the problem but I don't have a solution! The problem is that when I rewrite the Cookie nothing happens, even if I try to delete it, and rewrite it.
I have a cookie as an array User.remember = array('token' => TOKEN). When I try to rewrite the token, the cookie remains the same!
Maybe you are not defining the value (in number of minutes) of Session.cookieTimeout, you should define proper value for Session.cookieTimeout. If it is not defined it will use the same value as Session.timeout
Until now i always worked with session in Codeigniter. But now there is to much data for an session. I like to use cookies, but it doesn,t work for me.
I first load the cookie helper in the autoload.
I use this code to add data $this->input->set_cookie('users_new',$users_new);
var_dump($this->input->cookie('users_new')); With this one i tried to get the data. But it is empty. The variabele $users_new is filled with an array, so it cannot be empty.
When i try this simple example, the cookie is alsoempty.
$cookie = array(
'name' => 'some_value',
'value' => 'The Value'
);
set_cookie($cookie);
var_dump(get_cookie('some_value'));
die();
Whats wrong?
Thanks for your help!!
Cookies are sent by the browser so you would have to wait the user reload a page.
So the basic process is:
you set a cookie
the user resend the cookie on the next request
you can access the cookie value using get_cookie
EDIT:
setcookie is used this way, it won't work with an array
setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600); /* expire dans 1 heure */
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", "example.com", 1);
so you should do:
foreach ($cookie as $key => $val) {
setcookie($key, $val);
}
You should set an expiration value, i.e. seconds from the moment it gets created to when it will expire.
the "name" value must be a string, not an array. If you want multiple infos, you can just serialize() the array.
Example code:
$cookie = array(
'name' => 'users_new',
'value' => serialize($users_new),
'expire' => '86500'
);
$this->input->set_cookie($cookie);
You don't need to load the cookie helper if you just use the input class. No problem, I know, just to avoid useless lines of code :)
Cookies cannot hold arrays, just plain text. #RageZ had a good clue with the for loop which would set many cookies (as many as vars in array). #Damien suggests "serialized" and another option would be to jSon the array into a str with native php function "json_encode()"