第一种方式:
设计思路:
账号在密码输入错误3次进行5分钟时间锁定,在登录成功清楚掉错误登录信息和错误登录时间;在锁定登录之后,在进行时间验证并清除上次的错误登录信息和时间 保证不影响下次判断.
1.数据库设计 添加这个2个字段 登录错误次数 第三次错误登录时间

2.控制器层
注意一下 返回禁止登录的时间 加上5分钟
<?php namespace app\index\controller; use app\index\controller\Base; use think\captcha\Captcha; use think\Request; use Gucci\ServerResponse; use app\index\model\Index as IndexModel; use think\Cache; class Index extends Base { //验证码 public function getVerificationCode() { $list =new Request(); $code_id = $list->param('code_id',1);//验证码识别符默认1 // ob_clean();//tp5bug,获取验证码前清除缓存 $captcha = new Captcha(); return $captcha->entry($code_id); } / * @account string 账号 * @password string 密码 * @code 验证码 * @code_id 验证码识别符 默认1 * 登录验证接口 * @rerurn json / public function loginValidation() { $list =new Request(); $account = $list->param('account'); $password = $list->param('password'); //验证码废弃 用滑块 // $code = $list->param('code'); // $code_id = $list->param('code_id',1); // // $captcha = new Captcha(); // //判断验证码输入是否正确 // if( !$captcha->check($code,$code_id)) // { // // 验证失败 // return ServerResponse::createByError('验证码填写有误或以过期,请重新输入'); // } //判断账号密码是否正确 // $index = new \app\index\model\Index(); // $res = $index->login($account,$password); $res = IndexModel::login($account,$password,$list->ip()); if($res == 1) { return ServerResponse::createByError('账号不存在或禁止登录,请重新输入或联系超管'); }elseif($res == 2) { return ServerResponse::createByError('密码有误,请重新输入'); }elseif(is_array($res)) { return ServerResponse::createBySuccess('登录成功!',$res); }else{ //禁止登录 返回到禁止几点 $login_time =date('Y-m-d H:i:s', strtotime($res)+5*60); return ServerResponse::createByError('账号错误登录超过3次,账号已锁定,请于'.$login_time.'后;继续登录!'); } } //退出登录 public function logout(){ //清楚登录缓存 Cache::clear(); return ServerResponse::createBySuccess('退出成功!'); } }
讯享网
3.model层 和数据库交互
先查询登录信息,查询到在去判断错误登录次数和错误登录时间.在时间内直接返回 不在时间内

讯享网<?php namespace app\index\model; use Gucci\ServerResponse; use think\Db; use think\Model; use think\Cache; class Index extends Model { public static function login($account,$password,$ip){ //先查询登录 $user=Db::name('user') ->field('uid,password,user_name,role,is_logo,login_error_number,login_error_date') ->where(['account'=>$account,'ban_login'=>'0'])->find(); //先查询禁止登录次数和时间 是否够五分钟 不够直接返回 够了解除限制 $my_time = time()-strtotime($user['login_error_date']); if($user){ if($user['login_error_number'] >= 3 && 300 >= $my_time){ return $user['login_error_date'];//登录失败次数超过3 返回禁止登录时间 }else{ //查看登录时间如果超过5分钟 先把错误次数清空和错误时间 if(300 <= $my_time && !empty($user['login_error_date'])){ Db::name('user')->where('uid', $user['uid']) ->update(['login_error_number'=>0,'login_error_date'=>['exp', 'NULL']]); } //登录成功 信息写入缓存 2个小时 增加登录次数最后登录ip 还原登录错误次数 获取ip地址$_SERVER["REMOTE_ADDR"] $res = ServerResponse::think_encrypt($password); if($user['password'] == $res){ Cache::set('dy_user_name',$user['user_name'],'7200'); Cache::set('dy_uid',$user['uid'],'7200'); Cache::set('dy_role',$user['role'],'7200'); Cache::set('dy_is_logo',$user['is_logo'],'7200'); Db::name('user')->where('uid', $user['uid'])->setInc('login_number'); Db::name('user')->where('uid', $user['uid']) ->update(['last_ip'=>$ip,'login_error_number'=>0,'login_error_date'=>'']); return $user; //信息正确 }else{ //写入错误登录时间(第三次的时候写入)和错误登录次数 if($user['login_error_number'] == 2){ Db::name('user')->where('uid', $user['uid'])->setInc('login_error_number'); Db::name('user')->where('uid', $user['uid']) ->update(['login_error_date'=>date('Y-m-d H:i:s',time())]); }else{ Db::name('user')->where('uid', $user['uid'])->setInc('login_error_number'); } return 2; //密码错误 } } }else{ return 1; //用户不存在或禁止登录 } } }
总结:这种方法不是很高效,在面对高并发的情况下;对数据库压力大.因为验证在数据库中 所以得交互都得请求数据库,于是想到了新的思路 可以放到session里面 设计过期时间 也可以放在缓存中更加安全.
第二种方式:
设计思路:
把错误登录次数和错误登录时间放在缓存cache中 先去查询缓存信息 如果错误登录时间在直接返回. 登录失败时候 判断错误次数是否存在 不存在写入 存在2次 写上错误时间(为什么是2次 因为在程序从上往下执行 判断登录2次 其实已经是第三次登录失败了) 自增一次错误次数即可.
<?php namespace app\index\model; use Gucci\ServerResponse; use think\Db; use think\Model; use think\Cache; class Index extends Model { public static function login_now($account,$password,$ip){ //先查询缓存中是否有数据 错误登录次数 错误登录时间 $login_error_number = Cache::get('login_error_number'); $login_error_date = Cache::get('login_error_date'); if($login_error_date){ return $login_error_date;//返回禁止登录时间 } //在去查询用户登录信息 $user=Db::name('user') ->field('uid,password,user_name,role,is_logo') ->where(['account'=>$account,'ban_login'=>'0'])->find(); if($user){ //登录成功 用户信息写入缓存 2个小时 增加登录次数最后登录ip $res = ServerResponse::think_encrypt($password); if($user['password'] == $res){ Cache::set('dy_user_name',$user['user_name'],'7200'); Cache::set('dy_uid',$user['uid'],'7200'); Cache::set('dy_role',$user['role'],'7200'); Cache::set('dy_is_logo',$user['is_logo'],'7200'); Db::name('user')->where('uid', $user['uid'])->setInc('login_number'); Db::name('user')->where('uid', $user['uid']) ->update(['last_ip'=>$ip]); return $user; //信息正确 }else{ //查询缓存是否存在 if($login_error_number){ if($login_error_number == 2){ //写入错误登录缓存时间 Cache::set('login_error_date',date('Y-m-d H:i:s',time()),'300'); } Cache::inc('login_error_number');//缓存加1 }else{ Cache::set('login_error_number',1,'7200');//设置缓存 } return 2; //密码错误 } }else{ return 1; //用户不存在或禁止登录 } } }
总结 : 这种方便比上面的简单多了 少了代码量更容易理解 而且不用和数据库有太多交互 在高并发情况下也不会出现问题 如果是多点登录 可以在缓存变量名加入uid去分辨.
佳人未至清香至,人未起身心已动。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/42310.html