Forum Moderators: coopster

Message Too Old, No Replies

Limit the no. of currently logged in users on the same account

         

Claes100

3:05 pm on Jan 25, 2010 (gmt 0)

10+ Year Member



Hi,
I am developing a site in PHP+mySQL where our customers must log in to the site. In the first version each customer company will receive only one user id and password, in the 2nd version each person at each customer company will have to register.

In this first version I need to limit how many users at company x can be logged in at the same time (e.g. 20). All the log in and session handling is done today, I just need the limit. How do I do that?

I was thinking:

1) user logs in
2) NEW: check in dB if max no. of users reached for that company, if not count++;
3) set session var "userOK"
4) if Remeber me is checked => set hashed cookie
5) check if session is alive for each page access
6) NEW: if session not alive: before checking remember me cookie, count-- in database.

BUT, how would I decrease the counter when a user's session is no longer alive if that user just leaves their browser open without accessing another page or logs out?
Setting timestamps in the dB?

Any help or examples much appreciated!

/Claes

rocknbil

6:54 pm on Jan 25, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I think you might have to set an expiring cookie with the expire time to something short, like 5 or 10 minutes (or, you may be able to use a session variable for the same thing.) Record this expire time in the db. Each time the user requests a page, the cookie is updated, they get 5 more minutes. When the time passes, you delete their logged in entry from the DB, and it frees up the process for the next user.

A second approach would be on login, enter a time into the database. Same thing, every time this user requests a page, update the time. Then you write a cron job, run every five minutes or so, that does something like

delete from logged_in where last_login < date_sub(now(), interval 5 minute)

The second may be too intensive though, I'd try the first idea first.

By the way, there's no reason to do an internal increment. Using the above concepts,

$max_users = 20;

select count(*) from logged_in where last_login < date_sub(now(), interval 5 minute);

if ($logged_in >= $max_users) {
// Maximum users message here
exit;
}

Then you could use this login-triggered process to delete expired entries, no need for a cron or maintenance.

Claes100

9:25 am on Jan 26, 2010 (gmt 0)

10+ Year Member



Thanks rocknbil...
I liked the second approach but with no cron job. Just update the dB at every page access and if new users try to login, first deleteAllInactiveUsers() and then compare the $noOfActiveUsers with $max_users. If a user has been inactive for more than, say, 20 min, he needs to go through the login procedure above.

I don't have the experience to know if it would be too intensive for the dB to be updated at each page access...(?) and therefore I tried to understand the first approach with a timestamp in a session var but I didn't quite...
E.g., a very active user will get the session var updated at each page access with 10 more minutes, but the expire time in the dB will never be updated for that unique user. If that user is inactive for a long time, the dB won't be updated either. Then how would you know if the entry should be deleted or not if a new user tries to login (before login I must compare $noOfActiveUsers with $max_users)

Thanks again!
/Claes

rocknbil

9:02 pm on Jan 26, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



TYPO ALERT: my date math above is wrong, the < is backwards. I had it right, edited it to fix it, which made it wrong. :-) Corrected in the examples below.

select count(*) from logged_in where last_login > date_sub(now(), interval 5 minute);

Times in the past more than five minutes past will always be less than subtracting five minutes from the current time. You want to know if it's less than five minutes past to count active logged in sessions. <Doh>

-- all old -- 5 minute mark -- all still logged in

----------------------------------------

Something like this, roughly, not working code.

"logged_in" table

id¦user¦last_logged_in
int(11)¦int(11)¦datetime

You want datetime, not time, not timestamp, so it properly works with midnight, etc. Timestamp will work, it's just more difficult to read when checking data.

So user comes into a required login area, or the login script, you do whatever u/p validation you do, but also, do the count above. If it exceeds the max_logged_in, return the max users message. If not,

insert into logged_in (user,last_login) values('$user',now());

So they browse around the logged in area. Each time they request a page, you have a call to a function:

check_login($user);

function check_login($uid) {

(1) select (last_logged_in > date_sub(now(), interval 5 minute)) from logged_in where user='$uid';

....

(2) update last_login set last_logged_in=now() where user='$uid';

.... OR . . .

(3) delete from last_login where user='$uid';

(4) delete from last_login where last_logged_in < date_sub(now(), interval 5 minute)

}
1: This will return a 1 or a zero for the date math on last_logged_in; if the last time they made a request is more than five minutes old, it will return a zero. If it's less than five minutes old, it will return a 1.

Based on that, if that value is a 1, you do # 2, in which you reset the last_logged_in time to now(), giving them another five minutes. If the value is a zero, you delete this entry from the logged_in table, clear sessions, and return them to a login page with the session expired message.

(4) In any case, you would delete any entries here that are more than five minutes old, and yes, in this case, the less than < is correct. :-)

if it would be too intensive for the dB to be updated at each page access...(?) If that user is inactive for a long time, the dB won't be updated either.

See #4, it is "self cleaning" as it deletes old users from this small table when their session is more than five minutes old. As for intensive, I wouldn't think so, even with thousands of users, as it's constantly flushing out old entries every time a login-required page is requested.

In truth, #3 is not even needed as #4 will delete the over-five-minute entries - but it's there to describe the logic. If the date math returns a zero, you need to make sure to capture that value to redirect to the session expired message.

Last, make sure you put "5" in a variable somewhere so it can be easily changed, don't hard code it in . . .

Claes100

5:48 pm on Jan 28, 2010 (gmt 0)

10+ Year Member



Thanks again rocknbil for taking time,
implementation works perfect - just what I needed :-D

/Claes