I've binged a lot for this stuff, but couldn't find direct ANSWER,
I've searched for this here,
But
I am still beating my head against the wall trying to implement,
How do I do update query after session expired?
I'm not talking about explicit clicking "Logout" button
Here's basic SQL structure:
CREATE TABLE auth_users (
email varchar(40) NOT NULL,
password varchar(40) NOT NULL,
online ENUM('1') DEFAULT NULL <-- HERE, it updates to 1 when user logged in, it updates back to NULL when user explicitly clicks on LOGOUT
) type=MyISAM;
Class Hierarchy:
interface {
function login();
function logout();
//calls after succes authorization
function set_as_online();
//calls from within logout() method
function set_as_offline();
}
BUT IT DOES NOT UPDATES BACK TO NULL WHEN USER CLOSES HIS BROWSER,
For example,
Assume we have two users: User-A, User-B
User A logged successfully, now User-B can see User-A as ONLINE user.
If User-A forget to click "LOGOUT" and would close his browser,
user-B still can see User-A as ONLINE. That's the problem.
For example,
Facebook handles this very well,
Assume your friend just closed the browser (i.e his session does not exists anymore),
then somehow you can see him as OFFLINE
What am I doing wrong? Incorrect approach of handling offline/online users?
Another approach is needed here i think. Don't set a online/offline flag, but a 'last_seen' timestamp. Ie. with every request update the record to the current timestamp. If you want to know if the user is online, just do:
if($current_time - $last_seen_time < $session_expire_limit) {
// online
} else {
// offline
}
Otherwise you'd need a cronjob of some sort to automatically reset the online flag in your database after a certain time, but then still you'd need a last_seen column.
// edit
i don't know exactly how facebook does it, but it could be one of the following; for the chat and notify functionality facebook opens up a 'stream', which is in fact a little ajax call which is kept alive by the server (btw, this ajax call is refreshed every 40 seconds). Possibly this stream is used to track online users. Another option, but less likely, is that an event is attached to the window.unload event. This is less likely because a page refresh, a clicked link to another facebook page etc. is also triggering the event. This would mean that every time an internal facebook link is clicked the event should be unbinded from the browser.
Can't think of another way atm, just some suggestions. Unfortunately those are quite labor-heavy to implement, I assume my suggestion above (before the edit) should be suitable for a common website.
I am not sure how facebook controls this stuff but i can suggest you from the top of my head how i would approach this matter.
I would add a new field on your auth_users table of type Date that will represent the session_expiry_time .
Then inside your html pages you should implement some silent ajax code that will call a dummy php page on the server (the interval is something very important because you have to balance performance and functionality). This dummy page will update the session_expiry_time of the user in
the auth_users table.
Therefore, in any given time, checking a user's session_expiry_time against current time will determine if the user is online or not.
http://de2.php.net/manual/en/features.connection-handling.php
you can with register_shutdown_function() und connection_aborted() your intend achieve
Use a simple JavaScript on the page
In the body tag
The callLogoff() should be replaced with the JavaScript function that calls log off.
Try it.
Related
Here's the scenario, I have 2 user which is the Employee and Resident.
The Employee has an account on our website wherein they can see all the Residents' documents and they can select those documents so that the Resident can fill it up.
BTW the Resident doesn't have an account on the website. The only way they can fill up the said documents is by sending an email to them which contains an API or through a device that will be given to them onsite and has a login session of an Employee.
How can I prevent the Resident from navigating through other pages (Go back) once the device is given to them because the Employee cannot always monitor the Resident's action.
Thanks.
Edit: So what I've done previously is I have separate accounts for these users but after thinking thoroughly, an account for the Resident is unnecessary specially when they're too old to use devices. Logging in/out between Resident and Employee just to fill up documents will double up the process.
I'm thinking if it's good to save a session like
$session = $_SESSION['fillUp'];
whenever the Employee picks a document for Resident filling it up, then upon saving the document (which the Employee can only do) the form will then ask for a security code to be input by the Employee so that the document will be saved and unset the session.
Having that session checked on every other page except the document page if it exists will redirect the Resident to the document thus preventing navigation when filling up a document.
// Check session 'fillUp' for every controller except controller sign
public function beforeAction($action)
{
if (Yii::$app->controller->id != 'sign') {
$session = Yii::$app->session;
// session 'fillUp' contains the url of the document to be signed
if ($session->has('fillUp')) {
$this->redirect($session->get('fillUp'));
}
}
}
You will never stop people from using the browser's default navigation options. Whether than be browser back buttons, or swiping to navigate backwards. I've seen people in user experience testing sessions swipe to navigate backward by mistake.
Instead of trying to lock the door, we need to deal with what happens on the previous page(s) should they achieve the back navigation. Let's deal with the posibility that it may happen.
There are two pieces to what you're trying to achieve.
The first is to stop the browser from caching the previous page(s). This means any back navigation will trigger a request to the server to get the information.
We can stop this by adding headers to the page content of sensitive pages:
Send cache control: no-cache, pragma: no-cache and expire: -1 headers.
The second part is to decide what to do if somebody does navigate back, and the server gets a request for that page again.
You certainly want to mark the session as 'resident' on the first hit of the resident page. From there if the session has a 'resident' marker in the session, you may choose to show a warning with a link back to the page they should be visiting, or simply redirect them back to it without intereaction. Personally I think the warning with a link is clearer and will stop confusion.
I am currently using laravel 5.4, i get the list of online users, and i want from my admin-dashboard to make a specific user from my list to disconnect,
is there a way to do so ?
Set a flag in the database, for example, to mark the user as needing to logout. Then on their next request, in say a middleware, you can do:
if (Auth::user()->should_logout) {
Auth::logout();
}
There is a workaround to do this but I think it's
not optimum!
In users table we should have a field, say conected, then call an ajax request every 10 seconds (example), this ajax request is checking for connected field and sending user id, stating that user still is online, now when you change this field manualy, any time user click on a link or refreshes the page, they are logged out!
update:
#btl's idea to use window.reload() is good and does not need refreshing !
I'm currently trying to display all online users on my SITE'S userpage using the php session variables. To do this, whenever a user logs in or out, a column in a database gets set to "1" or "0".. However this doesn't entirely work since the database doesn't get updated when the user closes their browser (and therefor destroys the session). So is there another way of checking if a certain sessionid is set??
I also want to know how the twitter and facebook handle this ?
You almost have it. The way that the vast majority of sites deal with the issue is to have a table like you do, but they add a timestamp to it and update the timestamp when a new page is loaded.
When querying the table, you simply look for say the last five minutes of active users and they are the "live" users on the site.
Technically, you don't even need to keep the "logged in/out" value in that table. If they have been logged in within the lat five minutes, they are probably still about.
There is no guaranteed, sure-fire, totally bullet-proof way of checking if a user is there or not. You can do some tricky JS to ping on and off, you can add even more JS that will try to alert the db when the user navigates away from the page - but at the end of the day, you cannot do anything if a browser is closed unexpectedly, or if that user loses power, or network.
On top of that web browsing is by default stateless and doesn't maintain a connection to the user after the server has finished sending code. The best we can efficiently do is update a table when the user does something new and assume they will be around for a few minutes at least.
I haven't checked but Twitter and Facebook most likely have Javascript code which notifies the server when somebody closes the page, probably coupled with a periodic heartbeat and timeout.
Check the onunload event and XMLHTTPRequest to see how you can make a request to your PHP application notifying of an user leaving (a library like jQuery might help you do this much more easily).
Add a field "last_visit" to user's Table and update it every time when user visit your site
When user login to your site find "last_visit" time and current time,after that use this function
$time_period = floor(round(abs($current_time - $last_visit)/60,2));
if ($time_period <= 10)
$online_offline_status = 1;
else
$online_offline_status = 0;
}
and then print your final result
<?php if (
$online_offline_status == 0){ ?>
<span style="color:#FF0000;">Offline</span>
<?php } else if ($online_offline_status == 1) {?>
<span style="color:#669900;">Online</span>
<?php }?>
I'm facing an architecture problem I didn't manage to solve. I'm developing a little game in PHP and Javascript, and I need to save the user's progress. Now, the problem is that PHP can't determine when the user wins the level: it's done in Javascript. Is there any way to save the user's progress when he wins a level?
For example, when the user wins level 1, he gains access to level 2. If he tries to access level 2 without having completed the previous level, he gets redirected to the last completed one. In my controller I was doing the following:
if (1 !== $id) {
if ($app['session']->get('last_level') !== ($id - 1)) {
// redirect the user
}
}
Now I need a way to store the last_level value into the session, an operation that can't be simulated by the user.
Any hints?
You're going to want to do the different last_level calculations on the server. That way the user can't hack around with the JavaScript, and submit something on a specially crafted form. So depending on what your storage system is (KV store, Database, Textfile, etc.), put that value in there, and retrieve it.
Ajax can help you out, but isn't necessary. It depends on how your game is set up. But if they complete the level, the server needs to be notified.
If a user completes a level and then stays on the same page doing additional work:
Then you'll probably want Ajax to send the new level info to the server as soon as the new level has been achieved. Thus:
Use cookies to store your php session id
From your Javascript client, use Ajax to invoke a php url on your server whenever the user wins a new level. Send the new level as a parameter. Can use POST or GET, doesn't matter.
The php program will receive the session id in the cookie, and the new level as a parameter. The php program will look up the user id from the session id, then store the new level the database.
Next time the main url of the php program is invoked, it will be able to look up the user's level.
If the user presses "Next" button to go onward to the next level:
Use Javascript, not Ajax, to change the POST parameters of the "Next" button.
You'd use POST, not GET, since seeing a url of foo.com/game?level=5 is a bit too obvious for people to cheat your game. POST will not show the level parameter in the url. More security: add a checksum parameter.
If any of the above is not clear, ask in comments or as a follow-up question.
If you're happy to take javascript's word for it that the level has been completed then just set a cookie from javascript.
an operation that can't be simulated by the user
Sorry - but if it's javascript which dtermines when they've completed the level then there's nothing to stop the user falsifying the results.
Environment : PHP/MySQL/Jquery
I would like to refresh the page (ex: index.php) when new data stores in to the table (ex : new_entry_table) checking for every one minute. The same page will be opened in many machines(pc-browsers) at a time all should get refresh when new data arises.
using jquery and database check i tried the following:
setInterval(function(){
$.post("new_data_check.php", function(data) {
if(data > 0){
$("#container").fadeOut('fast').load(location.reload());
}
});
return false;
},60000);
new_data_check.php: : checks
for new data in the test_db where
newdata_field=0 ; : If any new
data arises echo "1"; And update the
newdata_field=1; to stop constantly
refreshing the page. : else echo
"0"; : Just for a trigger
So the above jquery code checks new_data_check.php every 1 min for the trigger , if any trigger arises it will refresh the container.But its getting refresh only one opened session other opened sessions(in other browser or other pc) not getting refreshed.
Suggest a better way to do this. Thanks.
Your new_data_check.php file will need to keep track of all the users that are independently viewing the page.
If not, this will happen:
User 1 and User 2 are both logged into the site.
User 1 does the check 5 seconds before User 1, there is new data.
User 1 completes his request. The server clears the new_data bit.
User 2's request arrives 5 second later. Hedoes his request, but at this point, User 1 has set the new_data field to 0. His data is stale, but User 1 has effectively co-opted him.
By the looks of it, you're not supplying it with any information that would identify the user - unless the server is determining that using the IP address. If that's the case, remember that it's likely everyone behind a small network is going to have the same external ip address. So it can't tell people at an office apart.
What you could do is generate some kind of unique hash for each session and pass that off to the browser. The javascript can then provide the php script that same token.
Another solution without any sort of special bit, would be to pass along a timestamp with the request. Essentially, the client says "my latest bit of data arrived at 9:21:53 PM" The server then checks and responds "My most recent data was created before that, so you're still good. " or "I've got something that was created or modified on 9:22:53PM, you should download it."
With that method, you don't need to worry about who's who. Instead, you need to have modification/creation times on the data you're checking for staleness. You also need to make sure that the clients clock is synchronized correctly - better yet, don't trust the clients date and time information. Maybe utilize your new_data_check.php to provide the script with a timestamp it can pass along on subsequent requests.