User limit in a PHP application

Asked

Viewed 1,100 times

3

Hello,

I developed a php system controlled by Sessions..

I found that it is possible to limit the maximum number of users online on the system via apache(httpd.conf).

Is there any function (ajax, javascript, php) that I can limit to 05 simultaneous users logged in to the system?

2 answers

1

Question: I found that it is possible to limit the maximum number of users online on the system via apache(httpd.conf)

No, this limiting sessions in apache is not done for users, the limits in apache would probably be to control connections, which does not guarantee you limit the maximum access of users to a site or page, nor is there any way to determine from this, since it is possible to maintain a session and there are various types of use for a connection, such as SSE or use the answer HTTP 100 Continue, or a single user can open more than one connection (for each tab or window that opens).

But none of these is the main subject, if you want to limit the number of users, first you need teach your system what a user is, user could be checked by IP maybe, what I think nay be a good idea, because the same IP on a network connected to the same internet provider (ISP) can be used by several computers, so what you can do is use the same sessions, however there is a great HOWEVER, it is not possible to detect when a user (which you taught your system "what is/when is") left/disconnected.

The only way to detect if the user has left is an idle time counter, meaning if a user is 5 minutes idle you can "kill" their session and determine for other users that that session for others is invalid, both factors, as well as "kill" and when to disregard for others will depend exclusively on time checking, ie you will not destroy/kill the actual session of that user, it is only a matter of logic.

Maybe someone will come and tell you about beforeunload could help, only I’ll give you an advance, beforeunload nay will work to detect when the user is leaving, more details on the subject in:

Even if you can apply all logic, you still need a database or a .txt (which can be much more complicated) to check all users, do not really need to be authenticated, the table should be something like:

CREATE TABLE usuarios (
    id INT NOT NULL UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    session VARCHAR(80) NOT NULL,
    lastactive TIMESTAMP
)

As users are accessing the table would be like this

id Session lastactive
1 22sin5grink0a22l80ej33mcj6 2018-06-24 01:00:23
2 ul5c6rkacb68suu6rqmd6dubt3 2018-06-24 01:00:33

Each generated Session in the table was created at the time the session was entered, ie the first time the user accessed, the script would be something like:

<?php

session_start();
require 'conexao.php';

define('MAX_USERS', 10); //Limite de 10 usuários
define('TIME_ONLINE', time() - 120);//120 = 2 minutos

$jaEstaOnline = false;

//Verifica se você já esta na "sessão" e dentro do limite de 2 minutos para considerar se estava ocioso ou não
$queryLogado = 'SELECT id TOTAL FROM usuarios WHERE
                session = ' . session_id() . ' AND
                lastactive > FROM_UNIXTIME(' . TIME_ONLINE . ')';


//Verifica só considera as linhas (usuários) no banco dentro dos minutos
$queryConta = 'SELECT count(*) as TOTAL FROM usuarios
               WHERE lastactive > FROM_UNIXTIME(' . TIME_ONLINE . ')';

if ($result = $mysqli->query($queryLogado)) {

    $row = $result->fetch_assoc();

    $jaEstaOnline = isset($row['id']); //Verifica se existe

    $result->free();
}

//Só executa a contagem se você estiver ocioso ou se for o seu primeiro acesso
if (!$jaEstaOnline && ($result = $mysqli->query($queryConta))) {

    $row = $result->fetch_assoc();

    if (!$row) {
        die('Erro na query');
    } else if ($row['TOTAL'] > MAX_USERS) {
        die('Já tem ' . MAX_USERS . ' usuários acessando');
    }

    $result->free();
}

//Verifica só considera as linhas (usuários) no banco dentro dos minutos
$query = 'SELECT count(*) as TOTAL FROM usuarios WHERE lastactive < FROM_UNIXTIME(' . TIME_ONLINE . ')';

if ($result = $mysqli->query($query)) {

    $row = $result->fetch_assoc();

    if (!$row) {
        die('Erro na query');
    } else if ($row['TOTAL'] > MAX_USERS) {
        die('Já tem ' . MAX_USERS . ' usuários acessando');
    }

    $result->free();
}

//Acaso chegar até aqui então irá atualizar o seu tempo no banco e irá determinar que você não esta ocioso, ou acaso seja o seu primeiro acesso irá te "registrar"
$query = 'REPLACE INTO my_table (session, lastactive) VALUES (session_id(), CURRENT_TIMESTAMP);';

if ($result = $mysqli->query($query)) {
   echo 'Você esta conectado';
} else {
   die('Você não esta conectado');
}

It would also be interesting to add something to erase all lines more than a week for example, so it would decrease unnecessary data in the database


How to check online users without bank

Yes it is possible to do with a .txt for example, but it’s much more complicated, because you’re going to have to write a logic on top of this, but something like this would be next to what you could do:

<?php

session_start();

$arquivoDeUsuarios = 'caminho/para/arquivo/usuarios.txt';

define('MAX_USERS', 10); //Limite de 10 usuários
define('TIME_ONLINE', time() - 120);//120 = 2 minutos

$users = array();

if (is_file($arquivoDeUsuarios)) {
     $unserialized = unserialize(file_get_contents($arquivoDeUsuarios));

     if ($unserialized) {
         $users = $unserialized;
     }
}

$id = session_id();

//Filtra e só considera os usuários não ociosos
$users = array_filter($users, function ($tempo) {
    return $tempo >= TIME_ONLINE;
});

//Verifica se é a seu primeiro acesso, se for vazio é porque é o primeiro ou vocÊ estava ocioso
if (empty($users[$id]) && count($users) > MAX_USERS) {

     //Se o count passar do MAX_USERS é por que tem mais de 10 usuários (ou o limite que você definiu)
     die('Já tem ' . MAX_USERS . ' usuários acessando');
}

//Atualiza o tempo ou adiciona você acaso for o primeiro acesso
$online[$id] = time();

//Salva os dados
file_put_contents($arquivoDeUsuarios, serialize($users));

But it’s important to note than wear a .txt may be something quite inefficient, someone may be able to record over each other’s information before the expected time, in this case working with LOCK (in php flock) along with a recursive check would help avoid problems like loss of recordings, or recording something on top, however this would make it too slow for users.

  • 1

    Very good!!! An Sqlite would be a good with this your rule applied.

  • 1

    @fabianophp thanks. Maybe Sqlite is not so good with competing connections, I can not say, however in Mysql there is the Engine memory, that Bacco suggested to me, maybe I create a question and/or answer about it, focused only on the usefulness of the memory.

-1

First, create a table with the following columns:

|-----------------------------------|
| IP varchar(15) | Views tinyint(1) |
|-----------------------------------|

Then, for each view, enter the IP (if not in the database) or increment the views by 1. If views = 5, kill the page and don’t allow the user to visit.

You can then run a cron every night at 00:00 which deletes all data in the table (study: truncate).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.