用户的锁定

之前由于做一个小项目的需要,做一个用户登录密码输错几次之后被锁定。但是本人还觉得还有瑕疵,就是在连续输错几次之后被锁定,但是目前实现的是时间上不连续错误几次就被锁定!

MODEL类中的代码

 class UserModel extends Model
    {
         protected $trueTableName ="mgj_administrators";

         // 数据映射
         protected $_map = array(  
          // 把表单中name映射到数据表的username字段   
               'username' =>'username',
                'userpassword'  =>'password', 
                // 把表单中的mail映射到数据表的email字段     
                );

        //检查用户名是否存在


       protected $_validate = array(   
            array('username','require','用户名必须'), 
             array('password','require','用户密码必须'), 
            // 都有时间都验证   
            array('username','checkName','帐号错误!',1,'callback'),  // 只在登录时候验证  
            // array('password','checkPwd','密码错误!',1,'callback'),
                // 只在登录时候验证 
        );


        public function  checkName()
        {

                $username = I('post.username');

                $map['username'] = $username;

                $res = $this->field('username')->where($map)->find();

                if(!$res){

                    return false;
                }   
        }


        // 处理登录
        public function signIn()
        {


            $data = I('post.'); 

            $map['username'] = $data['username'];

            $map['status'] = 1; 

            $userInfo = $this->where($map)->find();

            if(!$userInfo){

                return 1;//用户名不存在或者已经被禁用

            }
            //检查用户最近30分钟密码错误次数
            $res = $this->checkPassWrongTime($userInfo['id']);


            if(!$res){

                    return 30;//表示被禁用30分钟
            }


            $bool = password_verify($data['userpassword'], $userInfo['password']);

            if(!$bool){

                //记录密码错误次数
                $this->recordPassWrongTime($userInfo['id']);
                return 2;//密码不正确

                }else{

                // 登录成功,将用户信息保存在session中,不保存用户的密码
                unset($userInfo['password']);

                $_SESSION['mgjAdmin'] = $userInfo;

                return 3;//登录成功
            }

            if( $data['online']==1 ){

                $_SESSION['mgjAdmin']['username'] = $data['name']; 
                $_SESSION['mgjAdmin']['password'] = $data['userpassword']; 

                setcookie('username',$data['name'],time()+60*60*7*24); 
                setcookie('password',$data['userpassword'],time()+60*60*7*24); 

            }

        } 


        //这个方法是用来检验用户近30 分钟错误的次数
        public function checkPassWrongTime($uid, $min=30, $wTime =4)
        {

            if ( empty($uid) ){

                    throw new \Exception('第一个参数不能为空');

            }

            $time = time();//当前时间

            $prevTime = time() - $min*60;

            //用户登录ip
            $ip = -ip2long( $_SERVER['REMOTE_ADDR'] ) ;


            $map['uid'] = $uid;

            $map['pass_wrong_time_status'] =2;//表示错误的

            $map['ipaddr'] = $ip;

            $map['longintime'] = array( 'between', $prevTime, $time );

            $worngData = M('user_lock')->field('id,uid,ipaddr,logintime,pass_wrong_time_status')->where($map)->select();


           //错误次数的统计
            $worngTimes = count($worngData);

            // 判断错误次数是否超过了限制次数
            if( $worngTimes > $wTime ){
                // 如果错误大于了还需要查询最后一次错误的时间

                $map['uid'] = $uid;

                $userLockTime = M('user_lock')->where($map)->order('logintime desc')->find();

                if( $userLockTime['logintime'] -time() < 60*30 ){
                    // 将状态修改为1,正确状态
                    $data['pass_wrong_time_status'] = 1;

                    M('user_lock')->where("uid=".$uid)->save($data);
                }

                return false;
                }else{

                return true;
            }

        }


        //这个方法是用来记录密码错误的次数的
        protected function recordPassWrongTime($uid)
        {

            //ip2lon()函数可以将IP地址转化为数字
            $ip = ip2long( $_SERVER['REMOTE_ADDR'] );

            //时间为时间戳
            $time = time();

            $data['uid'] =$uid;

            $data['ipaddr'] = $ip;

            $data['logintime'] = $time;

            //状态为2表示正常,没有被锁定
            $data['pass_wrong_time_status'] = 2;

            M('user_lock')->add($data);

        }



    }


Controller中代码

class PublicController extends Controller
{
public function login()
{
if ( IS_GET ) {

                    $this->display('Index/login');

        }else if(IS_POST){  

            if (!D('User')->create()){    
         // 如果创建失败 表示验证没有通过 输出错误提示信息     
                exit(D('User')->getError());
            }

            //先判断验证码是否正确
            $bool = $this->checkCode( I('post.code') );

            if (!$bool ) {
                $this->error('验证码错误');
            }

            $res = D('User')->signIn();

            if ( $res==1 ) {

                $this->error('用户名不存在或者已经被禁用');

                exit;

            }else if($res==3){
                $this->assign('admin', $_SESSION['mgjAdmin']['username']);

                $this->success('登录成功', U('Index/index'));
                exit;

            }else if($res==2){

                $this->error('用户名或者密码错误');
                exit;

            }else if($res==30){
                $this->error('亲,你已经被禁用30分钟,一会儿再来!');

                exit;

            }

        }
    }

    public function makeCode()
    {

        $config =    array(   
         'fontSize'    =>25,   
         // 验证码字体大小 
            'length' => 4,  
        //验证码宽度、高度
            'imageW'  =>180,
            'imageH' =>50,
             // 验证码位数    
             );
        $Verify = new \Think\Verify($config);

        $Verify->entry();

    }

    public function checkCode($code)
    {

       // 将array(‘reset’=>false)错误了之后不清session中验证码以便于在此验证 array('reset'=>false) 
        $Verify = new \Think\Verify(array('reset'=>false) );

        if($Verify->check($code)){
            return  true;
        }else{

            return false;
        }
    }   

    //这个方法负责ajax验证码的验证
    public function  checkAjaxVerify()
    {

        if(!IS_AJAX)$this->error('亲,别乱来!',1);

        $codeVal = I('post.codeVal');

        if( $this->checkCode($codeVal) ){
            echo 1;
        }else{
            echo 0;
        }
    }

    // 这个方法负责ajax验证
    public function ajaxCheckUser()
    {
            if(!IS_AJAX){

                exit('亲,别乱来!');

            }else if(IS_AJAX){

                $userval = I('post.userval');
                // dump($userval);
                $map['username'] = $userval;
                $res = M('administrators')->where($map)->find();

                if(!$res){
                    echo 1;//用户名不存在
                }else{
                    echo 2;//有同样
                }
            }
    } 


    // 这个方法负责退出
    public function signOut()
    {

        // 先清除掉cookie,在清除掉session中的
        if(isset($_COOKIE[session_name()]))setCookie(session_name(),'',time()-1,'/');

        // 摧毁垃圾文件
        session_destroy($_SESSION['mgjadmin']);

        $this->display('Index/login');
    }


}

数据库的设计

--用户锁定表mgj_User_Lock ipaddr位
create table mgj_User_Lock(
id int unsigned auto_increment primary key,
uid int unsigned not null,
ipaddr int  not null,
logintime int  not null default 0 P COMMENT '用户登陆时间',
pass_wrong_time_status  tinyint(10) NOT NULL COMMENT '登陆密码错误状态1 启用 2禁用 '
)engine = innodb default charset= utf8;

alter table mgj_user_lock modify ipaddr int not null;

alter table mgj_user_lock modify logintime int not null default 0;
--commit"管理员表"status 为1启用,2禁用 
create table mgj_Administrators(
       id int  unsigned auto_increment primary key,
      username varchar(32) not null,
      password varchar(100) not null,
      status tinyint(1) unsigned default 1,
      pic varchar(50) not null,
      email  varchar(100) not null,
      addtime  int not null
)engine=innodb default charset =utf8;
alter table  mgj_Administrators add unique(`username`);
alter table mgj_Administrators modify password varchar(100) not null;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值