My goal is to share session between requests, I meant every request could reach a data. First I was thinking that simply sharing via filesystem could be good, but I find out this by myself:
session_id('0');
session_start();
echo session_id();
var_dump ($_SESSION);
if (!isset($_SESSION['x']))
{
$_SESSION['x'] = 0;
}
$_SESSION['x']++;
var_dump ($_SESSION);
this way I can see the same from browsers. My question is, is it a good practice?
EDIT: here is the full working version:
$m = microtime(true);
session_start();
if (session_id() == '0') // this happens when somehow our session id sticks, it should not happen ever, but if so, lets erase it
{
setcookie (session_name(), '', time() - 3600);
session_destroy();
session_write_close();
echo 'reload'; die;
}
if (!isset($_SESSION['x']))
{
$_SESSION['x'] = 0;
}
$_SESSION['x']++;
$saveId = session_id();
session_write_close();
// switch to common storage
session_id('0');
session_start();
if (!isset($_SESSION['common']))
{
$_SESSION['common'] = 0;
}
$_SESSION['common']++;
session_write_close();
// back to our own session
session_id($saveId);
session_start();
echo $_SESSION['x'].'<br>'.(microtime(true) - $m); die;
I dont thing its very time consuming.
It's tricky to know if SESSION is the right place to put this data, but it's worthwhile bearing some things in mind.
SESSION is designed to store data related to an individual user's visit to your site (normally being distinguished the combination of machine and browser, thanks to the session id being stored in a client side cookie).
Default behaviour of the PHP session handler is to:
Store the data in a file on the server.
Block concurrent access to that file.
It is possible to have multiple sessions for a given request, but that means ensuring you start and end each session and ensure that you keep track of the session IDs - I'm not entirely sure how you would do this without manually writing data into the client's cookie.
All in all you'll probably find that your performance using the session will be slower that just checking the existence of the file anyway (which is simpler than using the session, in terms of work done by PHP).
That said, if you're writing to that file then you're just going to have concurrency issues that you'll have to solve in much the same way as php sessions do anyway.
I'd say, if you're writing data, then look to your DB. It's what they're designed for.
If you don't want to write to your primary DB and have good reason for that, then maybe consider something like a memcache DB, or some other secondary storage.
Related
Running PHP 7.2.12 on a local Apache server (XAMPP on Windows).
I'm playing around with multiple sessions in PHP to see if I can stash away an open session, play around with a new one, and retrieve the previous session. I'm about to give up and just chalk it up to some kind of file locking thing.
The code that hangs ("connection reset" in Firefox):
//first session
session_start();
$old_id = session_id();
$old_session = $_SESSION;
$id = session_create_id();
session_commit(); //same as session_write_close()
//new session
session_id($id);
session_name('new_name');
session_start();
I don't particularly need any of the code to be this way, but I'm totally lost as to why this hangs due to this:
Comment out any one of the following lines:
$old_id = session_id();
$old_session = $_SESSION;
session_name('new_name');
And it doesn't hang. You can also replace session_create_id() with an alphanumeric string literal and it won't hang. It only seems to hang when all 3 of these optional lines are present, and when using session_create_id() to create a new collision free id. Is there a way to guarantee that it won't hang?
And for anyone who has time, I have another question: What would be the proper way to stash an open session, open/manipulate/save my own session, and then restore the original session?
This works:
//previous session
session_start();
$_SESSION['var'] = 'value';
//try to stash open session
$old_id = session_id();
session_commit();
//open new session
session_id('mySession');
session_start();
//modify and save my session
$_SESSION['var'] = 'mine';
session_commit();
//restore previous session
session_id($old_id);
session_start();
echo $_SESSION['var']; //output 'value'
But I'm afraid that once I start messing with new session names in combo with session_create_id() that I'll run into the hanging problem. Maybe I should check for session id collision without the use of session_create_id()? Or should I just try to piggy-back onto the already open session?
Edit: Maybe the core of what I'm asking is that if I make a PHP class that wants to pass anonymous data to/from the client, and somebody using my class opened a PHP session prior to using my class, what's the accepted way of handling that without stepping on the previous session? Ideally I want to name my session with something unique to the class, ie. not the default 'PHPSESSID'.
You ahe handling Session wrong in first example (you call session_create_id uselessly), it probably cause to hanging. Check logs if something info was here.
Maybe problem can be exhalted when you copy $_SESSION variable to another variable and then close session. As PHP internally works it can cause to unpredictable behavion, because $_SESSION is special type of array.
i'm having a bit of a problem. I'm trying to set up a simple webpage with only three .php pages. I want a session variable $_SESSION['userID'] to be set when a user is logged in and I want the index page to show extra info if someone is logged in.
On index.php I want to show some info, if a user is logged in I want to show some extra info.
login.php - simple log in form.
login_exe.php - takes care of database connection and verification.
So this was my idea:
On index.php, check if session is started, if not: start.
<?php
if (!isset($_SESSION)) {
session_start();
echo "session started";
}
later on, check if $_SESSION['userID'] contains a value, if so: print a string
if($_SESSION['userID'] != null){
echo "User logged in";
}
On login_exe.php i've almost the same code:
<?php
if (!isset($_SESSION)) {
session_start();
echo "session started";
}
in verification function:
$_SESSION['userID'] = $data['userID'];
header("Location: index.php");
The problem is that a new session is started on every page. How can I fix this and only start the session once? Thanks in advance
You should just put session_start() on top of documents that using sessions. Say, if you have 5 .php files that using sessions, then put 5 times the session_start() on top of them.
This is because session_start() sends headers and headers must be sent before any output (for example, any echo or whitespace).
Then, you should use something like isset($_SESSION["foo"]) and not just the entire $_SESSION array, where foo is something you set previously.
If you dont want sessions at all or need to reset the entire array, just call session_destroy() which effectively destroy the current session. Use unset($_SESSION["foo"]) when you want to get rid of a key.
Finally, you might get weird cases where you cannot read session key you write at. In these cases check what is the path of sessions and if they're writeable, or change their path:
$path = session_save_path(); // what is the path
is_writable($path); // can i write to it?
session_save_path("my/new/path"); // change the darn path;
// put -even- before session_start()!
:)
glad i help
I think the PHP manuals are really good compared to ...ahm, so just read about session_start(). It says:
session_start() creates a session or resumes the current one (...)
so all you need is session_start() very early in your code. This must be executed on every request (maybe as include).
Your code checking the userId looks fine, one important hint here: you should know exactly what isset(), empty() and the like mean in PHP, so always have the comparision of comparison at hand.
You should not ask new answers (edit: questions) in comments. Be as systematic here as you are in coding.
How to end a session:
This gives room for discussion, because there is the session cookie, which is client side, and the session data, which is server side.
I recommend:
$_SESSION = null;
Reason: this will clear all login and other associated data immediately. It leaves the cookie intact, which is normally of no concern, since all associated data is gone.
I have a situation where I've started a session with:
session_id( $consistent_session_name_for_user );
session_start();
$_SESSION['key'] = $value;
but then later I decide I don't actually want to "commit" (write) this session. PHP doesn't seem to have any kind of session_abort_write() function. I don't want to destroy the session variables from prior script runs, so I can't use session_destroy()
I tried session_id(""), but that call fails. I could "redirect" the session so it writes to another session, like session_id("trash"), but that would cause a lot of PHP (Apache) connections to try to write to the same session "file", which I want to avoid.
I'm highly simplifying the problem here, we're actually storing sessions in Memcached and this is a complex codebase. So I don't want to be sending unnecessary "trash" sessions to the Memcached server all the time.
From PHP.net,
session_regenerate_id
will replace the current session id with a new one, and keep the
current session information.
session_unset will free all registered variables
session_unregister ( string $name ) will unregister a specific variable
I haven't actually determined if this method prevents writing the session to the session store, but here's the solution I finally used:
session_id( 'trash' ); // or call session_regenerate_id() as someone else suggested
$_SESSION = array(); // clear the session variables for 'trash'.
I'm hoping this has the effect that nothing will get written, but I'm guessing it still will write a blank file, because PHP can't know that sess_trash isn't already there.
If you want to completely avoid writing the session, you'll have to use a custom session handler in PHP and set a global flag to prevent writing the session.
You could probably use something with session_set_save_handler to put dummy functions in for session handling.
<?php
function fakeIt() {
return true;
}
session_set_save_handler("fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt", "fakeIt");
There is session_write_close(). It dumps out the session array to storage and then "closes" it - $_SESSION will still be available and read/writeable, but any changes will no longer be saved, unless you do a session_start() again later on within the script.
I posted a similar question before, but never really got an answer that helped me, so I'm looking to try again. As a disclaimer, I know that a lot of the information in here doesn't follow perfect coding practices, but it is for exercise purposes only. I've tried a million things and nothing seems to be working because I'm not really sure where everything should go! I desperately need some (any!) help so thanks in advance if you can offer anything!
I'm trying to create a simple form / page that uses some basic cookie and session stuff to produce some user-specific data. I was moving along good until I came across a few problems that I can’t figure out. On my first page everything is good except for I just want the NAME of the browser the user is using. (for example, I want just the simple title: Firefox instead of the whole long version of the browser.) I've seen this be done so I think it’s possible, I just don’t know how to do it!
My real problems come up right about here, because I'm not exactly sure how to store the IP address, browser info and the current date/time (which I want shown on page 2) as session variables. Tried a few things I found, but I don’t think I was doing it right.
I also worked endlessly on trying to store the username and passwords as two separate cookies each...suggestions? Finally, what do I need to do to have a location header (used to call form_data.php) with output buffering?
(Not sure this will be that helpful, considering I probably did everything wrong! LOL) This is a totally stripped-down version of my code. Tried to post my cleanest version, even though it doesn't have much info, so that you could easily see what I was trying to do.
main file code:
<?php
header('Location: form_data.php');
setcookie('username', $_POST['username']);
setcookie('password', $_POST['password']);
//I know this isn't working.
//honestly I just left this in here as to show where I had been
//trying to save the cookie data. Pretty obvious how bad my
//trial and error with this went!
}
?>
<?php
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
echo " By the way, your IP address is: </b>".$_SESSION['ip']."<br />";
echo " You already know this, but the browser you are currently using
to view this page is:<br/>"; //What is the correct function that I should be using here?
echo "<form action=\"form_data.php\" method=\"post\">";
echo "username:<input type=\"text\" name=\"username\" size=\"20\" value=\"\"><br/>";
echo "password:<input type=\"password\" name=\"password\" size=\"20\" value=\"\"><br/>";
echo "<input type=\"submit\" value=\"Submit, please\" />";
echo "<br /><input type=\"hidden\" name=\"submitted\" value=\"true\" />";
?>
form_data.php
<?php
echo "Hello, ".$username;//I'm trying to get the cookie data for the username
echo "Your password is ".$password; //Samething here (want cookie data)
echo "The date and time you entered this form is: ".date("F j, Y")." -- ".date("g:i a");
echo "<br/>Your IP:".$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
echo "<br/>Your broswer:".;//I want full broswer data here...dont know how to do it.
//Overall, was this the way to get the session variables for IP, date/time and browser?
echo "Thank you for filling out this form!";
?>
To get the browser, use the get_browser() function:
$browserinfo = get_browser($_SERVER['HTTP_USER_AGENT']);
$browsername = $browserinfo['browser'];
Your session and cookie storage will never work because you are making a header("Location"); call before attempting to set cookies. You cannot send any output before setting cookies or establishing a session.
Before any output to the screen, call session_start();
// attach to your session (or create if it doesn't exist)
// You must call session_start() on every page where you intend to access or set session vars
// and it must be called before any output (including whitespace at the top)
session_start();
// Store some stuff...
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
// Store user info in session, not cookie
$_SESSION['username'] = $_POST['username'];
// Set a cookie
// Not a super secure token, but better than user/pass in cookies.
// Point here is just to show that it must be done before any output or before the redirection header.
$_SESSION['token'] = sha1(time() . rand() . $_SERVER['SERVER_NAME']);
setcookie('token', $_SESSION['token']);
// In practice, you'd want to store this token in a database with the username so it's persistent.
// Now do the redirection:
// Supposed to be an absolute URL by the HTTP spec
header("Location: http://example.com/form_data.php");
// exit right after the redirection to prevent further processing.
exit();
ADDENDUM after comments
While you work, make sure PHP displays all errors on screen. Be sure to turn off display_errors when your code goes onto a live public server.
error_reporting(E_ALL);
ini_set('display_errors', 1);
To retrieve values from cookies as you said in your question you didn't know how to do, use the $_COOKIE superglobal:
// On the page that sets it...
setcookie('somename', 'somevalue', expiry, domain);
// On the page that retrieves it...
echo $_COOKIE['somename'];
> I'm trying to create a simple form /
> page that uses some basic cookie and
> session stuff to produce some
> user-specific data.
Sessions do use cookies under the cover(only store session_id inside cookie/set_cookie) and I advice you to use only sessions because cookies can leak information(store all the information inside cookie on that user's computer) which could be dangerous while session uses the server's filesystem/database or whatever you like when you override session_set_save_handler.
> On my first page everything is good
> except for I just want the NAME of the
> browser the user is using.
Like Michael said you can use get_browser for that:
Attempts to determine the capabilities
of the user's browser, by looking up
the browser's information in the
browscap.ini file.
Like the PHP page says it tries to determine and you should NOT rely on this information for anything important because it can be wrong(you can fool the system, if you like). What I mean is you should not use it to validate/proof something.
> My real problems come up right about
> here, because I’m not exactly sure how
> to store the IP address, browser info
> and the current date/time (which I
> want shown on page 2) as session
> variables.
More information to retrieve the IP address can be read here(proxy-server could mislead you a little bit maybe?). To store that information just store it inside a session by first issuing session_start() on top of every page(before outputting anything) that wants to use sessions(only those to not set cookies on every page which makes page a little slower) and next store the current time inside a session variable by doing something along the lines of $_SESSION['time'] = date(DATE_RFC822);. You can read more about retrieving the time at date() page.
So the code on page 1 looks something like:
<?php
session_start();
$_SESSION['ip'] = getRealIpAddr(); # no php function => See http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html
$_SESSION['time'] = date(DATE_RFC822);
Then on page 2 you could retrieve this information using something like:
<?php
session_start();
echo $_SESSION['ip']; // retrieve IP
> I also worked endlessly on trying to
> store the username and passwords as
> two separate cookies
> each...suggestions?
Don't store them inside a cookie(only using set_cookie and not using sessions to store information) but store them inside a session for extra security. But sessions are also vulnerable to session fixation so after storing something critical inside your session you should regenerate session id and never output/show that information to the browser/user to prevent any leakage.
> Finally, what do I need to do to have
> a location header (used to call
> form_data.php) with output buffering?
Like Michael said you should be using header function and exit to terminate script after that
<?php
header("Location: http://www.example.com/"); /* Redirect browser */
/* Make sure that code below does not get executed when we redirect. */
exit;
?>
P.S: Never store any really sensitive information like creditcard(use paypal or something) numbers or anything in your own database. I also advice you not to store passwords inside your database but use something like openId(Google's) for example to handle your authentication for extra security.
I have always wondered, if a PHP session times out during the middle of executing a script, will the contents of the $_SESSION array still be available until script execution ends? For example:
session_start();
if(! isset($_SESSION['name'])) {
echo 'Name is not set';
exit;
}
// imagine there is a bunch of code here and that the session times out while
// this code is being executed
echo 'Name is ', $_SESSION['name']; // will this line throw an error?
Is it practical to copy session variables to the local scope so I can read them later on in the script without having to keep checking for a session time out? Something like:
session_start();
if(isset($_SESSION['name'])) {
$name = $_SESSION['name'];
} else {
echo 'Name is not set';
exit;
}
// bunch of code here
echo 'Name is ', $name;
don't worry about such things. Nothing will happen to the session. It's initialised by sessioni_start() and $_SESSION will be always available within your script.
The default three-hour session lifetime is reset each time you open the session (see session_cache_expire), so the only way a session could time out in the middle of a request is if a request takes three hours to process. By default PHP requests time out after just 30 seconds, so there's no danger of session expiry during a request. Furthermore, the $_SESSION variable won't suddenly change in the middle of a request. It's populated when the session starts, and that's it.
The variables are copied into the $_SESSION global at the initial request, so it has the same effect as copying it to a local variable.
However, for clarity sake, it makes sense to copy it to a local variable. Especially if you plan to use the variable several times. It can be difficult to read code that has $_SESSION['variable'] all over the place.
What you needed to understand is how sessions work. A client accessing a script using a $_SESSION super global only knows the key to the session that belongs to them (Stored in Cookie/URL). This means the session data itself has nothing to do with the client. If you have the key to the session data you want to use then you can use it. Older versions of PHP had some security holes because sessions where stored somewhere that was easily accessible (I don't remember details).
Basically, if you have the session id in a PHP script you have access to that session unless the memory on the machine is flushed/harddrive is corrupt (ie Computer Restart/Device Failure).
Hope this helps, otherwise go to php.net and dive into the details on how sessions work.