>  Q&A  >  본문

php - 用memcache如何做用户登录失败限制?

我要限制用户一小时内登陆只能密码输错12次,如果在最近一小时内累计密码错误超过12次就直接不能登录,如何用memcache实现,不用mysql,因为碰到mysql的login log表越来越大,之前mysql的实现方式太慢了

迷茫迷茫2724일 전486

모든 응답(2)나는 대답할 것이다

  • 天蓬老师

    天蓬老师2017-04-10 16:11:57

    如果你不需要记录用户登陆的历史详情,只是想要限制登陆次数就非常简单

    1. 为每个用户创建一个特别的key(举个例子,user_login_count_${用户ID}

    2. 每次登陆的时候拿到用户名,就去memcache去取这个key的value,如果发现其值已经超过12,则在此时报错说明只能尝试12次

    3. 如果不存在这个key,那么通过set新建,并把值记为1,expire时间设置为3600秒

    4. 如果登录失败,那么对这个key对应的value进行increment的操作,并重新设置超时时间为3600秒

    5. 如果登陆成功,则直接清除这个key的内容

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-10 16:11:57

    因为 @vimac 的答案没有解决最近一小时问题,以下仅提供个思路,细节还可以完善

    <?php
    // 存储失败次数时间戳
    $key = "user:{$user_id}:login_failed";
    $login_failed = $mem->get($key) or array();
    $allow_times = 12;
    if(! checkAllowTimes($login_failed, $allow_times)){
        throw new Exception("allow times max", 1);
    }
    
    if(! passValid($user_id, $password)){
        array_unshift($login_failed, time());
        // 最多存 12 条记录
        if(count($login_failed) > $allow_times){
            $login_failed =  array_slice($login_failed, 0, $allow_times);            
        }
        
        $mem->set($key, $login_failed, 3600);
    }else{
        // 登录成功删除失败记录,取决于是连续失败还是累计失败?
        $mem->delete($key);
    
        // ...
    }
    
    function passValid($user_id, $password){
        // ...
        // 伪代码
        return true or false;
    }
    
    function checkAllowTimes($login_failed, $allow_times){
        $last_hour = strtotime('1 hours ago');
        for($i = 0; $i < count($login_failed); $i++){
            // 如果已经登录失败 12 次
            if($i >= $allow_times - 1){
                return false;
            }
    
            // 1 小时前的登录记录不检索
            if($login_failed[$i] <= $last_hour){
                return true;
            }
        }
        return true;
    }

    회신하다
    0
  • 취소회신하다