Home  >  Article  >  Backend Development  >  How to implement persistent login function in ThinkPHP3.2.2

How to implement persistent login function in ThinkPHP3.2.2

不言
不言Original
2018-05-05 15:16:501431browse

这篇文章主要介绍了ThinkPHP3.2.2实现持久登录(记住我)功能的方法,涉及ThinkPHP操作cookie记录登陆信息的相关技巧,需要的朋友可以参考下

本文实例讲述了ThinkPHP3.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

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

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




 
 Document





视图 个人中心 ucenter.html




 
 Documenttitle>
<script type="text/javascript" src="/js/jquery.3.5.2.min.m.js"></script>
</head><div style="position: fixed;right: 0;top:100px;width: 125px; z-index:2000;"><div ><a target="_blank" rel="nofollow" href="https://www.520xingyun.com/from/188bet.php" ><img width="120px" height="550px" src="https://www.520xingyun.com/images/188_120.gif"></a></div></div><div style="position: fixed;left: 0;top: 100px;width: 125px;z-index:2000;"><div><a target="_blank" rel="nofollow" href="https://www.520xingyun.com/from/188bet.php"><img width="120px" height="550px" src="https://www.520xingyun.com/images/188_120.gif"></a></div></div>
<body>
 <if condition="$session['username'] neq null">
 <i>{$session.username},</i>
 <else />
 <i>游客,</i>
 </if>
 欢迎您<br>
 <a href="__CONTROLLER__/loginout">退出登录</a>
</body>
</html></pre><p></p>
<p><strong>附:模块目录</strong></p>
<p><img alt="" src="https://img.php.cn/upload/article/000/153/291/30ccf8fd0b771bb9ee45d22b3a283a38-0.jpg"></p>
<p>相关推荐:</p>
<p><a href="//m.sbmmt.com/php-weizijiaocheng-292617.html" target="_self">thinkphp3.2.2实现生成多张缩略图的方法,thinkphp3.2.2多张_PHP教程</a></p>
<p><br></p>
<p></p>
<p class="clearfix"><span class="jbTestPos"></span></p><p>The above is the detailed content of How to implement persistent login function in ThinkPHP3.2.2. For more information, please follow other related articles on the PHP Chinese website!</p></div><div class="nphpQianMsg"><div class="clear"></div></div><div class="nphpQianSheng"><span>Statement:</span><div>The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn</div></div></div><div class="nphpSytBox"><span>Previous article:<a class="dBlack" title="Simple implementation method of customizing Action, Model and View in thinkphp3.x" href="//m.sbmmt.com/m/faq/395352.html">Simple implementation method of customizing Action, Model and View in thinkphp3.x</a></span><span>Next article:<a class="dBlack" title="Simple implementation method of customizing Action, Model and View in thinkphp3.x" href="//m.sbmmt.com/m/faq/395354.html">Simple implementation method of customizing Action, Model and View in thinkphp3.x</a></span></div><div class="nphpSytBox2"><div class="nphpZbktTitle"><h2>Related articles</h2><em><a href="//m.sbmmt.com/m/article.html" class="bBlack"><i>See more</i><b></b></a></em><div class="clear"></div></div><ul class="nphpXgwzList"><li><b></b><a href="//m.sbmmt.com/m/faq/347584.html" title="round robin weighted round robin algorithm php implementation code" class="aBlack">round robin weighted round robin algorithm php implementation code</a><div class="clear"></div></li><li><b></b><a href="//m.sbmmt.com/m/faq/347592.html" title="PHP strip_tags() function to remove HTML, XML and PHP tags from strings" class="aBlack">PHP strip_tags() function to remove HTML, XML and PHP tags from strings</a><div class="clear"></div></li><li><b></b><a href="//m.sbmmt.com/m/faq/347593.html" title="Introduction to PHP strip_tags() to remove HTML, XML and PHP tags" class="aBlack">Introduction to PHP strip_tags() to remove HTML, XML and PHP tags</a><div class="clear"></div></li><li><b></b><a href="//m.sbmmt.com/m/faq/347595.html" title="PHP removes html tags--detailed explanation of the difference between strip_tags and htmlspecialchars" class="aBlack">PHP removes html tags--detailed explanation of the difference between strip_tags and htmlspecialchars</a><div class="clear"></div></li><li><b></b><a href="//m.sbmmt.com/m/faq/347602.html" title="PHP strip_tags method to retain multiple HTML tags" class="aBlack">PHP strip_tags method to retain multiple HTML tags</a><div class="clear"></div></li></ul></div></div><div class="nphpFoot"><div class="nphpFootBg"><ul class="nphpFootMenu"><li><a href="//m.sbmmt.com/m/"><b class="icon1"></b><p>Home</p></a></li><li><a href="//m.sbmmt.com/m/course.html"><b class="icon2"></b><p>Course</p></a></li><li><a href="//m.sbmmt.com/m/wenda.html"><b class="icon4"></b><p>Q&A</p></a></li><li><a href="//m.sbmmt.com/m/login"><b class="icon5"></b><p>My</p></a></li><div class="clear"></div></ul></div></div><div class="nphpYouBox" style="display: none;"><div class="nphpYouBg"><div class="nphpYouTitle"><span onclick="$('.nphpYouBox').hide()"></span><a href="//m.sbmmt.com/m/"></a><div class="clear"></div></div><ul class="nphpYouList"><li><a href="//m.sbmmt.com/m/"><b class="icon1"></b><span>Home</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/course.html"><b class="icon2"></b><span>Course</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/article.html"><b class="icon3"></b><span>Article</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/wenda.html"><b class="icon4"></b><span>Q&A</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/dic.html"><b class="icon6"></b><span>Dictionary</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/course/type/99.html"><b class="icon7"></b><span>Manual</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/xiazai/"><b class="icon8"></b><span>Download</span><div class="clear"></div></a></li><li><a href="//m.sbmmt.com/m/faq/zt" title="Topic"><b class="icon12"></b><span>Topic</span><div class="clear"></div></a></li><div class="clear"></div></ul></div></div><div class="nphpDing" style="display: none;"><div class="nphpDinglogo"><a href="//m.sbmmt.com/m/"></a></div><div class="nphpNavIn1"><div class="swiper-container nphpNavSwiper1"><div class="swiper-wrapper"><div class="swiper-slide"><a href="//m.sbmmt.com/m/" >Home</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/article.html" class="hover">Article</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/wenda.html" >Q&A</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/course.html" >Course</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/faq/zt" >Topic</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/xiazai"  >Download</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/game" >Game</a></div><div class="swiper-slide"><a href="//m.sbmmt.com/m/dic.html" >Dictionary</a></div><div class="clear"></div></div></div><div class="langadivs"  ><a href="javascript:;" class="bg4 bglanguage"></a><div class="langadiv" ><a  onclick="javascript:setlang('zh-cn');" class="language course-right-orders chooselan "  href="javascript:;"><span>简体中文</span><span>(ZH-CN)</span></a><a  onclick="javascript:;" class="language course-right-orders chooselan chooselanguage"  href="javascript:;"><span>English</span><span>(EN)</span></a><a  onclick="javascript:setlang('zh-tw');" class="language course-right-orders chooselan "  href="javascript:;"><span>繁体中文</span><span>(ZH-TW)</span></a><a  onclick="javascript:setlang('ja');" class="language course-right-orders chooselan "  href="javascript:;"><span>日本語</span><span>(JA)</span></a><a  onclick="javascript:setlang('ko');" class="language course-right-orders chooselan "  href="javascript:;"><span>한국어</span><span>(KO)</span></a></div></div><script>            var swiper = new Swiper('.nphpNavSwiper1', {
                slidesPerView : 'auto',
                observer: true,//修改swiper自己或子元素时,自动初始化swiper
                observeParents: true,//修改swiper的父元素时,自动初始化swiper

            });
        </script></div></div><!--顶部导航 end--><script>isLogin = 0;</script><script type="text/javascript" src="/static/layui/layui.js"></script><script type="text/javascript" src="/static/js/global.js?4.9.47"></script></div><script src="https://vdse.bdstatic.com//search-video.v1.min.js"></script><link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css' type='text/css' media='all'/><script type='text/javascript' src='/static/js/viewer.min.js?1'></script><script type='text/javascript' src='/static/js/jquery-viewer.min.js'></script><script>jQuery.fn.wait = function (func, times, interval) {
    var _times = times || -1, //100次
    _interval = interval || 20, //20毫秒每次
    _self = this,
    _selector = this.selector, //选择器
    _iIntervalID; //定时器id
    if( this.length ){ //如果已经获取到了,就直接执行函数
        func && func.call(this);
    } else {
        _iIntervalID = setInterval(function() {
            if(!_times) { //是0就退出
                clearInterval(_iIntervalID);
            }
            _times <= 0 || _times--; //如果是正数就 --

            _self = $(_selector); //再次选择
            if( _self.length ) { //判断是否取到
                func && func.call(_self);
                clearInterval(_iIntervalID);
            }
        }, _interval);
    }
    return this;
}
$("table.syntaxhighlighter").wait(function() {
    $('table.syntaxhighlighter').append("<p class='cnblogs_code_footer'><span class='cnblogs_code_footer_icon'></span></p>");
});
$(document).on("click", ".cnblogs_code_footer",function(){
      $(this).parents('table.syntaxhighlighter').css('display','inline-table');$(this).hide();
});
$('.nphpQianCont').viewer({navbar:true,title:false,toolbar:false,movable:false,viewed:function(){$('img').click(function(){$('.viewer-close').trigger('click');});}});
</script></body></html>