my code is simple:
<?php
session_start();
session_regenerate_id();
?>
When the first time I request this page, the HTTP request with no cookie, then it will response with two 'set-cookie:PHPSESSID=xxxxxx'
Then I thought that I may write code like this:
<?php
session_start();
if(!empty($_SERVER['HTTP_COOKIE'])){
session_regenerate_id();
}
?>
While then, whether my HTTP request with cookie: PHPSESSID=xxxxxx or not, it will responses with only one 'set-cookie:PHPSESSID=xxxxxx'
However, my solution is very awkward.
Any professional PHPer can tell me, how to write a professional code to handle the problem which is the HTTP request may with cookie 'PHPSESSID' or without cookie 'PHPSESSID'.
Have a look at session_start()
session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
So when you not want that PHPSESSION-Cookie you need to remove session_start()
Set cookie with setcookie('cookie_name', 'some_value') and then get the cookie with $_COOKIE['cookie_name']. Check difference for cookie and session so you are sure you need a cookie for your operation :)
Related
on every page (first lines, first code) I have those two lines of code:
define("DIRECT_ACCESS", true);
defined("DIRECT_ACCESS") OR die(header("Location: https://website.com/"));
after those two lines of code, I always do session_start();, I read that session_start() should come as a first thing, before anything. Session_status() shows that session is active and working properly, so I have a couple of questions:
1. Why does the session work if it should be the first line, before other code?
2. Is there anything dangerous that can happen, could something stop working later if I don't put session_start() as the first line of code?
Thanks for your time trying to help me.
I read that session_start() should come as a first thing, before anything.
That statement is basically wrong.
There're a few things to take into account when initialising sessions:
With the default (and recommended) settings, session ID is transmitted through a cookie. Server-side cookies are set through HTTP headers. HTTP headers need to be sent before response body. Thus you need to avoid constructs like this:
echo 'Hello, World!';
session_start();
You cannot use session data before it's retrieved from the persistent storage. That's precisely what session_start() does. So you cannot do this:
$user_name = $_SESSION['user_name'];
session_start();
Some times you may want to close the session in order to unlock the storage. You do that with session_write_close(). Once you do that, session data remains loaded but changes won't persist. So please avoid:
session_write_close();
$_SESSION['user_name'] = 'john.doe';
Other than that, you're free to start sessions whenever you see fit.
I made a simple registration page, which after validation, adds a unique identifier to the session id to identify the user and also sets a session variable 'UID' to a custom value. Then the script redirects to a new page.
$_SESSION['UID'] = $id;
session_id($sessID);
echo session_id();
session_write_close();
header("Location: https://localhost/AccountWebsite/landing.php");
exit();
?>
The landing page is supposed to be accessible only by members (i.e. those with a special unique session id set by my script), and that functionality wasn't working. So to check why, at the moment I allow anyone to access the page and their session id is echoed, and so is the 'UID' session variable.
<?php
session_start();
echo session_id()."\n";
echo $_SESSION['UID'];
?>
Now, when I echo the id it isn't the one I set myself. It is the generic PHP one, and the variable doesn't exist. During debugging, I commented out the redirect in the registration script, and instead had it echo the session id that it had just set. The echoed id is correct (obviously since it's echoed in the script it's set in), although when I enter the cookie manager on Firefox, it displays the session id as the generic php one, which means the session is reset when the first script ends and not between sessions.
Make sure session_start(); is called before any sessions are being
called. So a safe bet would be to put it at the beginning of your
page, immediately after the opening php tag before anything else.
Also ensure there are no whitespaces/tabs before the opening php
tag.
After the header redirect, end the current script using exit(); (Others have also suggested session_write_close(); and
session_regenerate_id(true), you can try those as well, but I'd use
exit();)
Make sure cookies are enabled in the browser you are using to test it on.
Ensure register_globals is off, you can check this on the php.ini file and also using phpinfo(). Refer to this as to how to turn it off.
Make sure you didn't delete or empty the session
Make sure the key in your $_SESSION superglobal array is not overwritten anywhere
Make sure you redirect to the same domain. So redirecting from a www.yourdomain.com to yourdomain.com doesn't carry the session
forward.
Make sure your file extension is .php (it happens!)
I have done all of the above from dayuloli's answer on this post
and have been debugging all day. Please help, why does the session not keep the id and variable values I set to it by the end of the script and sccross the whole server?
Additional info: I tried another example folder (on htdocs) where one page sets a variable and the other echoes it, and it worked.
You don't need to set a session_id unless you want multiple sessions. If you do specify a session_id, you need to call session_start() afterwards to start using it and submit the cookie into the client's browser.
Beyond that explanation, you need to use session_start() at the top of any script that requires sessions.
From http://php.net/manual/en/function.session-id.php:
session_id() needs to be called before session_start()
session_id() will always send a new cookie when session_start() is
called
i have a strange problem, when i use setcookie in PHP with session, while my browser is open, everything work fine, but when I close it, then I can't pass $_SESSION from page to another page!
in login page I have:
$_SESSION['name'] = $_POST['name'];
$_SESSION['pass'] = $_POST['pass'];
$life=2592000;//1 month
setcookie(session_name(),session_id(),time()+$life);
header("location:administrator/");
die();
I used session_start(); in every page on top of them, also I used this code for logout:
session_start();
unset($_SESSION['name']);
unset($_SESSION['pass']);
session_destroy();
header("location:../");
an important note is when I checked browser cookies, before closing browser there are tow cookie and their contents value is exactly same like each other, one expire at the end of session but another expire one month latter, which I like to be, but then I close browser and return back, there are tow cookie but with different values! which I think case problem and session variables don't pass from page to page.
Apart from the problem mentioned by #Matt (you may need some custom mechanism to restore or reinstantinate session using cookies), keep in mind that using mod_rewrite or actual directories messes with cookies path! To make sure the cookie is available when and where you need it, add additional parameter / (PHP setcookie(), $path parameter)
I would like to know if there is a way to prevent PHP from sending a cookie when calling session_start().
My use case is for a site optimisation:
(1a) I first open a session/send headers.
(1b) Then generate and output some text content.
(1c) To enhance session read/write I call "session_write_close" as soon as I don't need to write in the session anymore.
(2) Finally I have a post-page rendering process (for stats) that requires a write access to the session. The session is closed, I cannot call session_start() again since it sends a cookie and it's to late for that. This is a computation-heavy process, so I have to do it after the page is sent to the client.
The client already received a session-cookie. So I don't need session_start() to send a new (and redundant) one.
Does someone know a way to intercept the cookie or something similar ? Of course I want to avoid the "Cannot send session cookie - headers already sent". This error is invisible for the user because the page is already renderered but it looks ugly in the logs.
My question seems to be a redundant one, but it is not. I know how headers and content work (send headers first, content after). It's just that PHP does not let me do what I want.
I would like to know if there is a way to prevent PHP from sending a cookie when calling session_start().
Yes there is, by telling PHP to not use cookies for sessions. The PHP setting is session.use_cookies:
ini_set('session.use_cookies', 0); # disable session cookies
session_start();
By default cookies are enabled because they are considered more safe then using URL parameters (see Sessions and securityDocs).
(2) Finally I have a post-page rendering process (for stats) that requires a write access to the session. The session is closed, I cannot call session_start() again since it sends a cookie and it's to late for that. This is a computation-heavy process, so I have to do it after the page is sent to the client.
It's probably possible to tell PHP that the cookie is already set by adding it into the $_COOKIE superglobal arrayDocs. I never experimented with it, but in case you use session_start() and PHP sees that the session cookie has been already set (by the browser, not PHP, $_COOKIE represent the browser cookies), it won't send the headers (again) to set the cookie (which as I understand you is what you want).
Edit: Some test script to play around with:
<?php
header('Content-Type: text/plain;');
echo "Incomming Cookies:\n";
print_r($_COOKIE);
// to simulate that this is a new session, the session cookie is removed
// which makes PHP think it is a new session when invoking session_start()
// unset($_COOKIE['PHPSESSID']);
// run the first session
session_start(); // creates the session cookie (as we don't have one yet)
printf("Session %s has been started: %s\n", session_name(), session_id());
var_dump($_SESSION);
$_SESSION['variable'] = isset($_SESSION['variable']) ? $_SESSION['variable']++ : 0;
session_commit();
printf("Session has been closed, remaining id is: %s\n", session_id());
// visual confirmation that session cookie has been created
echo "Outgoing Cookies:\n";
print_r(headers_list());
// run the second session
ini_set('session.use_cookies', 0); # disable session cookies
session_start();
printf("Second session %s has been started: %s\n", session_name(), session_id());
var_dump($_SESSION);
$_SESSION['2nd-variable'] = isset($_SESSION['2nd-variable']) ? $_SESSION['2nd-variable']++ : 0;
session_commit();
You need to call it with a web-browser (and PHP sessions must be configured to work).
I thought I should mention another great way to prevent the cookie (and the cache limiter) headers from being sent when calling session_start.
The session_start call takes an options array where you can set any of the session. prefix variables, and you can disable these things for just that call.
session_start(array(
'use_cookies' => '0',
'cache_limiter' => ''
));
Note that use_cookies keeps the cookie from being sent, and setting the cache limiter to an empty string keeps it from updating the cache headers (not the best documented feature).
Here are two notices that this will fix (this is helpful when you need to work through multiple sessions).
Warning: session_start(): Cannot send session cookie - headers already sent
and
Warning: session_start(): Cannot send session cache limiter - headers already sent
You can use ob_start() function to buffer the headers/content, you may clear the buffer contents using ob_clean()
I've got a script that sets some session values before redirecting to / using header().
I've read many posts about the $_SESSION variable being destroyed / lost after header(), even after I implemented this:
// set session here
session_regenerate_id(true);
session_write_close();
header("Location: /");
session_start() is set in the correct places, does anyone know of anything that I might be missing?
On the index.php page I have this:
session_start();
print_r($_SESSION);
// outputs nothing :'(
The code is pretty complex so will not post it all, just snippets.
I've never seen any session related issues due to using location headers - are you sure you're calling session_start on both pages?
Hmm... this answer made a lot more sense before you added the session_start bits above, and mentioned the fact that you were sure you were using session_start. :-)
header must be sent before session close
session_regenerate_id(true);
header("Location: /");
// the header must be sent before session close
session_write_close(); // here you could also use exit();
just put exit; after header :D I solved by this
After the Header redirect you need to exit the PHP script:
header("Location: /");
exit();
In the interest of closing this question, we had concluded it was a problem with the server configuration, not surprising considering the host is well known for this kind of thing.
One possible option that was not mention here and happened to me is that I was creating another session. When you're using session in php you can use only one session at a time. If you create a new session the old one is lost. This is more likely to happen when you create a session for login and maybe you want another session for something else(It's not that recommended anyway). My case was a flash() method which I used to create a session only once a post was added/updated/deleted. And use that session in the views to display a message then destroy it. Every time I created a new session while adding/updating/deleting the other session that I used for login was destroyed. This is not something that happens to often but it's possible.
I had the same problem, I found that using a function related to Session helps to ensure if you started a session or not
if(session_status == PHP_SESSION_NONE)
session_start();
You don't need to start session_start() in each page. cuz untill your browser is closed the same session remains for the entire path you have specified in php.ini