ThinkPHP 3.2.2 实现持久登录 ( 记住我 )

来源:互联网 发布:linux装telnet包 编辑:程序博客网 时间:2024/05/16 14:04

ThinkPHP 3.2.2 实现持久登录 ( 记住我 )

实现持久登录,即用户在登录时,勾选了"记住我"之后,无论是否关闭浏览器,只要不退出登录,在指定的时间内始终保持登录状态(缺点是在另一台电脑上登录过后,之前那台电脑就不能继续保持登录状态)。

首先,持久登陆使用 cookie 实现,但是 cookie 中不能保存用户密码这样重要的信息,即使加密过。解决方案是在用户登录表中新建3个字段identifier:第二身份标识,token:永久登录标识,timeout:永久登录超时时间。

+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| uid | int(11) | NO | PRI | NULL | auto_increment |
| uname | varchar(20) | YES | | NULL | |
| upwd | varchar(20) | YES | | NULL | |
| uflag | int(11) | YES | | NULL | |
| identifier | varchar(32) | YES | | NULL | |
| token | varchar(32) | YES | | NULL | |
| timeout | int(11) | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+

在用户勾选了"记住我"登录时,应该生成一个唯一的 identifier,一个唯一的 token,并且设置一个过期时间 timeout,把两个代表身份的值写入cookie,设置 cookie 过期时间为 timeout,例如:setcookie('auth',"$identifier:$token",$timeout); 同时把三个值插入数据表;当用户再一次访问网站时,首先判断 cookie 中是否含有 auth,如果含有,则去数据库中进行身份比对(identifier 和 token),比对成功时,把用户信息写入 session,同时用户保持登录状态。

 

代码:

控制器 TestController.class.php

复制代码
<?phpnamespace Test\Controller;use Think\Controller;class TestController extends Controller {    public function login(){        //判断是否永久登录        $this->checkLong();        //已经登录则跳转至个人中心        if(isset($_SESSION['username'])){            $this->redirect('Test/ucenter');        }else{            //判断是否存在cookie            if(isset($_COOKIE['username'])){                $this->assign('username',$_COOKIE['username']);            }            //显示注册页            $this->display("test");        }    }    //显示验证码    public function verifyImg(){        $verify = new \Think\Verify();        //$verify->useZh = true;  //使用中文验证码        $verify->length = 4;         $verify->entry();    }    //验证登录    public function check(){        $verify = new \Think\Verify();        if($verify->check(I("yzm"))){            //判断用户名密码            $user = new \Test\Model\TestModel();            $res = $user->checkName(I("username"),I("pwd"));            if($res === false){                echo "用户名或密码错误";            }else{                //用户信息存入session                session("username",$res['uname']);                session("id",$res['uid']);                //如果用户勾选了"记住我",则保持持久登陆                if(I("remember")){                    $salt = $this->random_str(16);                    //第二分身标识                    $identifier = md5($salt . md5(I("username") . $salt));                    //永久登录标识                    $token = md5(uniqid(rand(), true));                    //永久登录超时时间(1周)                    $timeout = time()+3600*24*7;                    //存入cookie                    setcookie('auth',"$identifier:$token",$timeout);                    $user->saveRemember($res['uid'],$identifier,$token,$timeout);                }                //把用户名存入cookie,退出登录后在表单保存用户名信息                setcookie('username',I('username'),time()+3600*24);                //跳转至会员中心                $this->redirect('Test/ucenter');            }        }else{            echo "输入错误";        }    }        //测试strstr函数    public function strstrtest(){        $param = "Think\Verify";        //第三个参数为true,返回'Think';没有第三个参数,返回'\Verify'        $name = strstr($param,'\\',true);        echo $name;    }    //用户中心    public function ucenter(){        //判断是否永久登录        $this->checkLong();        $this->assign("session",$_SESSION);        $this->display("ucenter");    }    //退出登录    public function loginout(){        session(null);        setcookie('auth', '', time()-1);        $this->redirect("Test/login");    }    //生成随机数,用于生成salt    public function random_str($length){        //生成一个包含 大写英文字母, 小写英文字母, 数字 的数组        $arr = array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));        $str = '';        $arr_len = count($arr);        for ($i = 0; $i < $length; $i++){            $rand = mt_rand(0, $arr_len-1);            $str.=$arr[$rand];        }        return $str;    }    //判断是否持久登录    public function checkLong(){        $check = new \Test\Model\TestModel();        $is_long = $check->checkRemember();        if($is_long === false){                    }else{            session("username",$is_long['uname']);            session("id",$is_long['uid']);        }    }}
复制代码

 

模型 TestModel.class.php

复制代码
<?phpnamespace Test\Model;use Think\Model;class TestModel extends Model{    //验证登录信息    public function checkName($name,$pwd){        $admin = M("admin");        $info = $admin->getByUname($name);        if($info != null){            //验证密码            if($info['upwd'] == $pwd){                return $info;            }else{                return false;            }        }else{            return false;        }    }    //当用户勾选"记住我"    public function saveRemember($uid,$identifier,$token,$timeout){        $admin = M("admin");        $data['identifier'] = $identifier;        $data['token'] = $token;        $data['timeout'] = $timeout;        $where = " uid = ".$uid;        $res = $admin->data($data)->where($where)->save();        return $res;    }    //验证用户是否永久登录(记住我)    public function checkRemember(){        $arr = array();        $now = time();        list($identifier,$token) = explode(':',$_COOKIE['auth']);        if (ctype_alnum($identifier) && ctype_alnum($token)){            $arr['identifier'] = $identifier;            $arr['token'] = $token;        }else{            return false;        }        $admin = M("admin");        $info = $admin->getByidentifier($arr['identifier']);        if($info != null){            if($arr['token'] != $info['token']){                return false;            }else if($now > $info['timeout']){                return false;            }else{                return $info;            }        }else{            return false;        }    }}
复制代码

 

视图 登录页 test.html

复制代码
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title></head><body><form action="__CONTROLLER__/check" method="post"><if condition="$username neq null">    <input type="text" name="username" placeholder="用户名" value="{$username}"><br><else />    <input type="text" name="username" placeholder="用户名"><br> </if><input type="password" name="pwd" placeholder="密码"><br><input type="text" name="yzm" placeholder="验证码"><img src="__CONTROLLER__/verifyImg" onClick="this.src=this.src+'?'+Math.random()"><br><input type="checkbox" name="remember" id="remember"><label for="remember">记住我</label><input type="submit" value="提交">    </form></body></html>
复制代码

 

视图 个人中心 ucenter.html

复制代码
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title></head><body>    <if condition="$session['username'] neq null">    <i>{$session.username},</i>    <else />    <i>游客,</i>    </if>    欢迎您<br>    <a href="__CONTROLLER__/loginout">退出登录</a></body></html>
复制代码

 

附:模块目录

 

参考资料:

php持久登录、记住我功能实现:http://blog.csdn.net/clh604/article/details/20282945

php生成包含数字,大小写英文字母的随机字符串:http://www.oschina.net/code/snippet_616695_22223

转自:http://www.cnblogs.com/dee0912/p/4285221.html

原创粉丝点击