如何限制php中每个用户的并发登录次数

时间:2012-07-05 11:15:57

标签: php login

我想根据管理员设置阻止用户的并发登录。

如果admin将并发登录设置设置为3,则用户可以一次从3个不同的位置登录。

如果用户尝试从第4位登录,则应用程序不应允许用户登录。

知道如何通过数据库维护这个。请帮忙。提前谢谢。

3 个答案:

答案 0 :(得分:5)

您可以维护一个具有活动用户会话的数据库表,其中会话被视为活动状态,如果上次用户活动发生的时间少于X分钟(可配置值)。

每次用户尝试对登录表单进行身份验证时,您应该检查该用户当前有多少会话处于活动状态,并根据该检查确定是否对其进行身份验证或拒绝使用某种形式的响应消息

答案 1 :(得分:0)

Fully working example (download)

您所做的就是在用户表中添加一个额外的列,并将其命名为登录。每当用户登录时将列递增1,并且在登录脚本中,您可以检查登录次数是否等于限制,当用户注销时,您将登录次数减少1。

使用此方法可能出现的问题是,如果用户未注销且服务器无法再次识别会话,则不会减少登录。为了避免这种情况,更好的方法是在下面。

  1. 创建一个登录的列名,并为其提供varchar(500)或最好是文本的数据类型,因为可能很难预测我们期望的数据大小。

  2. 当用户登录时,检查登录列是否为空,如果为空,则使用time()函数创建包含session_id的json,登录时间。

    if($column_login == '' or count(json_decode($column_login)) == 0){
        $login_json = json_encode([
                        ['session_key'=>'session_key_generated', 'time' => time()]
                    ]);
    //then update the logins table with the above
    }
    
  3. 如果登录列不为空或解码时列的计数大于零,则检查计数是否大于登录限制,如果登录次数还不大于登录次数limit,然后将新会话附加到数据库表中的logins列

    if(count(json_decode($column_login)) > 0 and count(json_decode($column_login)) < $login_limit){
        $login_json = json_decode($column_login);
        $login_json[] = ['session_key'=>'session_key_generated', 'time' => time()];
        $login_json = json_encode($column_login);
        //update the logins column with the new $login_json and log the user in
    }
    
  4. 如果达到登录限制,则检查登录并检查具有过期时间的登录限制,例如,假定未激活300secnds的用户已注销,然后删除会话已从表中过期

    if(count(json_decode($column_login)) >= $limit){
        $logins = json_decode($column_login);
        foreach($logins as $key =>  $login){
            if($login['time'] < time()-300){
                //this checks if the iterated login is greater than the current time -300seconds and if found to be true then the user is inactive
                //then set this current login to null by using the below statement
                $logins[$key] = null; // or unset($logins[$key]) either should work;
    
            }
    
        }
    
        //after iteration we check if the count of logins is still greater than the limit
        if(count($logins) >= login_limit){
            //then return a login error that maximum logins reached
        }else{
            //then login is successsfull
        } 
        //update the logins column to equal to json_encode($logins);
    }
    
  5. 在已记录用户的任何请求中,您检查会话密钥是否仍存在于数据库的登录列中($ logins ['session_key']),如果未找到,则记录日志用户立即退出以避免权利升级,否则将$ login ['time']更新为新时间()。

  6. 此方法效果很好。

答案 2 :(得分:0)

我已经基于@MaheshKathiriya实现了一些东西

我有一个名为Query query = collectionRefference. .whereEqualTo("menuID", "categoryID") .whereEqualTo("status", "available"); 的表,该表具有列“ id”(PK,AI),“用户名”,“密码”,“登录”
user将数组转换为字符串,而serialize()将序列化的字符串转换回数组

在登录列中,我插入了一个包含子数组的数组(我们称之为main_array)。
main_array中的子数组数量表示DB中已注册会话的数量。
子数组具有两个值,session_id和time_of_login。

每当用户登录时,我们都会检查main_array中子数组的数量。

如果main_array为空,我们将插入一个具有相应session_id和时间的新子数组,并允许用户登录。

否则,如果主数组不为空,则检查其中有多少个子数组。如果子数组的数量大于0且小于login_limit,则我们插入一个新的子数组并允许用户登录。

否则,如果main_array中的子数组数量等于或大于login_limit,则我们检查会话unserialize()
是否过期 如果会话在过去60秒钟内没有激活,我们将从主阵列中删除该子阵列。
现在,我们再次检查main_array中子数组的数量是否等于或大于login_limit,如果小于登录限制,则允许登录并将新的会话sub_array插入主数组。 否则,登录失败(因为没有活动会话可以替换当前尝试登录的用户) 将一个新的子数组插入到main_array中,并带有相应的session_id和登录时间。

(sub_array['time']>time()-60, means this session was active more than 60 seconds ago)
相关问题