Questions about making 'if user is online' system - php

Please help start in the right way . I want to add 'if user is online' system. Which I will use to prevent multiple logins under 1 name, also this system will add option to users showing them who is online at the moment.
I understand that I need mysql table where I will store online users. But how can I understand each second if user is still here? if he logs out then ok, it's easy, but if he will restart? or something else ? So how can I controll all users and understand per second their status ?
UPDATE After some discussions with Cupcake I decided to have only who's online feature, letting 1 user to log in multiple times, cause it's difficult to prevent him from doing that in a comfortable way.

renew this table record each time user requests a page, updating access time field.
delete from this table all records which access time field is older than some reasonable timeout like 5 min
to prevent multiple logins under 1 name you have to store session id in the users table.
when user logins, stire current session id in this field
every time user requests a page, compare this id against actual session id, and make user relogin

What you could do, which is what I sometimes do, is this, in the user table have a column named session_hash or something similar.
And each time the user logs in, generate a new session hash yourself or use the session_id PHP has, as long as you use session_start on each page.
Then to retrieve the users row from the database, have a cookie with that session_hash.
Example
Login form
Username: [ ]
Password: [ ]
Remember?: [*]
[ Login ]
PHP page does the following
User logs in ->
System generates a session_id or "salt"
Updates the users row with the session_id or "salt" value
Check if the value of the "remember" checkbox is true ->
Sets a cookie with that session_id or "salt" with a month or so expiration date
Otherwise just create a normal cookie with the value
Then on each page do the following
Check if the session_id or "salt" cookie is set ->
If it is, fetch the users row from the database
SELECT * FROM users WHERE session_id/"salt" = value of cookie
What all this does if lets the user choose if they want to be remembered each visit, if they do create a cookie that doesn't expire for at least a month that way they will be remembered next time they come to the site, but if they login from another browser or computer the "salt" won't be valid on the other computer.

Simply invalidate all old sessions of the user, once he opens a new one. In that way, he can only run one session (aka one login) at a time.

Related

Best way to prevent simultaneous login

I know this is a recursive question, but, I haven't found a new solution, or a solution based on the new frontend frameworks or technologies.
I've a Vue + PHP application that users can olny log once per time. My current solution to block concurrent access is making a call to a PHP page with Ajax from 5 to 5 minutes storing the time. I store a flag in DB too, whether it has been registered or not. So, when the user try to log in, I check if the time is greater than 6 minutes or the flag is set to 0.
I think this is not the best way to do this. When the application has too many users it can cause too much load on the server.
There is a way to do like Netflix? An warn when triyng to connect and was logged in another machine.
If your end goal is to have it so that any given account can only be logged into one machine at a time, generate a unique ID at login and write that ID to the database for that user. Set that ID as a cookie for the user. When you receive traffic from that user, only consider them logged in if their cookie matches the value in the database.
When the user logs in to a new device, a new unique ID is generated and sent as a cookie to that new device. The new device's traffic has a cookie that matches the database, and is therefore considered logged in. When the old device visits your application, the login cookie no longer matches the value in the database, so that user is considered logged out.
When the old device logs in again, a new unique ID is generated in the database and sent as a cookie to that device. They are now logged in, because their cookie matches. The second device, having its cookie no longer match the database, is logged out.
This solution doesn't require you to access the database on every page, reducing database load significantly.
Add a field for sessionID to your user table in the database.
Set the default session handler before calling session_start() (needed for the next line of code to work):
session_set_save_handler(new \SessionHandler());
On every successful login, retrieve the stored $sessionID from the database. Destroy the old session with:
(new \SessionHandler())->destroy($sessionID);
Get the new session ID with:
$sessionID = session_id();
Store the new session ID to the database.

Combine PHP session and MySQL for query login state

My compeny current PHP website has users that are logging in using session. Keeping a field in the session $_SESSION['user_id'] and when logging out unset this field. The user data like Name, Address, Balance is saved in MySQL user table. Now I want to create a query that returns all the logged in user and Balance is over 500$.
How would you approach such task?
Consider that I have a lot of users so looping through all the sessions in session folder and than querying the DB and than matching the results in not really a possibility.
Second option is saving user login state in the user table. setting it to 1 when user log in and to 0 when log out. This is the simplest option to do with current code base and the company bureaucracy.
But I can think problem with synchronization especially if the session expire
Third option is to transfer all the responsibility of the session to the DB with something like session_set_save_handler.
What do you think is the best practice?
(I'd like to add to what #Ofir_Baruch said, for avoiding multiple calls to the DB in order to update last user's loggin all the time)
Add a time-stamp "last login",in:
user's table in DB (lets call it: DB's time-stamp)
in user's session (lets call it: session's time-stamp)
(lets say a session lasts 15 minutes for example)
Add this concept when you check if user's session is valid:
(pseudo code)
when user request a page:
if session[user] is not valid:
create new session
session[user] = username
session[last-login] = time-stamp
update user's last login column in DB to current time-stamp
else
if ( current_time_stamp - session[last-login] > 15 )
session[last-login] = time-stamp
update user's last login column in DB to current time-stamp
else
do_nothing
this way, you don't have to update the DB's time-stamp each time your user does something (like requesting a page or refreshing), but only if 15 minutes have passed.
getting the all logged user's will be a simple query now, as #Ofir_Baruch described in comment.

Allow just one PHPSESSID per user

I've created a webservice, on which users can log in sending an oauth token. As response, this webservice returns a PHPSESSID cookie to keep the user logged in.
However, if you do log in several times, a new ID is generated each time. Examples:
ts1i3plmdcnmoivai637a27oe1
bhn1snms8kajmpo8ape5e5ctj3
d5467idr1ree9dcq6h9cqt9oj2
en2vbo1r62fqmrriid8l4rkvd3
All those 4 ID's are valid.
Is there any way make this sessid unique per user? So for example, when ID#4 is generated, previous 3 are discarded. Then I could handle a 403 error or whatever.
On the other hand, a second question:
Is it possible to make this PHPSESSID token longer?
If you want that then it's better to use your own cookies instead of php sessions.
You'll need to generate a random cookie key when someone log in, I'll call that random cookie key as cookie_id.
Then you need to store it in the database with the user_id it's connected to, so you can make a new table in database called sessions, with cookie_id and user_id fields (user_id needs to be unique), or you can extend your user table with cookies_id field.
After saving the cookie_id value with it's related user in db, you'll give that cookie_id to that user through cookies.
You can verify logged-in user with his cookie_id.
When logging out cookie_id will be null in db.
When another login happen, new cookie_id will be written over the old cookie_id in db.
That's it
Also You can set the period of your cookie with the expire parameter: http://php.net/manual/en/function.setcookie.php
For more security you can make cronjobs to delete cookie ids from db after some period of time. (You'll need to store the login date to do so)

Avoiding multiple logins to an account from different locations

I want to restrict multiple logins of the same user from different locations. How can I identify a user's multiple logins from different locations in the same/recent times? I think some flags and IP checking in a table might be a possible solution, but are there any better solutions?
Update:
I think the session or cookie might help if it for a single machine. Like when users log in for the first time create an activation key and store it, and every other time when users login to that machine, check the cookie value. likewise.
I would resolve something like that by making in user table, a activeKey column. Everytime user is logging in the activeKey is changed ( simple way subchar(md5(time().$username), 0, 16)), and and store it in session. Every time the webpage is refreshed/entered key would be checked. If dosn't match then logout with info. On correct logout key would be set to NULL, so when it could give a flag.
This metod could be combined with IP address, but only IP address could be cheated, same with MAC, and so on.
That is a main idea. There could be additional data like last login date, IP last login date, and so on.
You can have a table containing the IDs and the IP addresses of the users that are currently logged in. Just check against this table everytime someone logs in.
Here's a solution that doesn't require constant database access to work...
(which will avoid the requirement to check the session_id() against the database value every time you request/refresh a page, relieving db/server stress)...
1. On login, grab the pre-existing session_id stored in the DB for this user and do this:
session_id("the pre-existing session id in the database goes here");
session_start();
session_destroy();
2. Then start a new session and save this new session_id to the database, overwriting the previous one. This will logout the previous session on this user if there is one active (effectively logging out the other guy using this account).
Give it a try and let me know if that does the trick!!
NOTE: This is "in theory" as I haven't yet tried it. It's based on this accepted stackoverflow answer. And you should probably manually create the session_id based on something unique to each user, that way you don't wipe out a session that someone else is using that happened to be the same as the session last used by the user you are doing a check for.
I think, just have extra 2 columns for each user - "LastLoginTime" and "IPAddress" in your Users table. If the duration is too short and IPAddress vary then you can give a warning to the user. Additionally you can also inform the City & Country from which the user is logged in.
I would add in the users table an ipAddress column, a LastLogin date column, LogStatus column with boolean values (actually MySQL uses 1/0 for boolean) to check if the user is logged in or not, a Country column (although this could be bypassed by using proxy), and a blockedStatus column, again with 1/0 values, that would check if the user is blocked or not.
Then at log in page, you'd check if the user is logged in then he can't login, if he was recently logged in, and the country is different, then something is happening and you would need to block the account and send a email with a link to unblock the account if the legitimate user was the one logging in.

How to Prevent Concurrent User Logins in PHP/MySQL Site?

I am developing the user management portion of a website that will host a webcast. The goal is to prrevent the same user nam (email address) from being used concurrently. That is, we don't want two individuals using one login to view the event.
I've already setup a table that holds the user registration data with regID as primary key. My thought is to create a login history table with username as primary key, foreign key to user name in registration table. The login history table would simply timestamp when the user logs into the site. However, this won't accomplsih my goal of preventing more than one individual from using the same login name.
Instead, would it be better to have a login status field either in the login history or user table that is set to 1 for logged in and 0 for logged out? It would need a stored procedure to update the value at login and at logout, and would need to be validated when a user logs in such that if login status = 1, user already logged in and cannot login a second time. Is this a feasible approach?
Please share other methods you've used to prevent the same login credential from being shared amongst multiple individuals.
Thanks,
Sid
If it is OK to logout an already logged in user if someone else logs in with the same credentials then you could do the following: when a user logs in generate a random ID in your database for that user and the same in a cookie session. The two must match to authenticate.
Without rolling your own session handler, you could do a little parallel tracking. When a user logs in, you can store the user's session ID and login time in the database (maybe inside the user information table). The login script could then check for the existence if this sessionID and allow/deny login based on the presence of the session ID. If the ID's null/blank, then the user logs in. If there's a session ID present, and it's more than X minutes old, allow the login. Otherwise deny them.
Of course, you'd probably want to roll your own session cleanup handler at that point, so that when stale session files get deleted, you can remove the associated IDs from the database at the same time.
The problem here is detecting the user is logged in (i.e. whether he didn't logout).
One possible way is to register in the database the time of his last activity and the time of his explicit logout. You could then deny a login if it this was attempted less than say 5 minutes ago relatively to his latest activity and if he didn't login in between.
You could force "activity" by having the website pages periodically poll the server with Javascript.
It's easy to determine when someone logs in. It's much harder to determine when someone logs out. If you have a mechanism of killing the webcast streaming to a particular user quickly, you might want to have something which pops up asking the user if they want to kill their other session if you think there might be one active.
How are you doing user sessions on the server? If you store them in the db, you could query the active sessions anytime someone attempts to log in and see if they're already in there. Of course you'd probably also have to check some kind of timestamp since you're not guaranteed that sessions will disappear at session.gc_maxlifetime.
You might want to consider making a global variable in php to store a hash array with login status. This has the benefit that if the application has to be restarted for some reason, the user isn't stuck in the wrong state in the database.
You can store a mapping from user ID to IP or session cookie and redirect requests that come with different information to the login page. If the user logs in, the other session would be invalidated and further requests in the last session forward to the login page.

Categories