本文实例讲述了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
<?php
namespace 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
<?php
namespace 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>Documenttitle>
</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格式化美化的排版工具帮助大家在以后的PHP程序设计中进行代码排版:
php代码在线格式化美化工具:http://tools.phpstudy.net/code/phpformat
更多关于thinkPHP相关内容感兴趣的读者可查看本站专题:《ThinkPHP入门教程》、《ThinkPHP常用方法总结》、《smarty模板入门基础教程》及《PHP模板技术总结》。
希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。
本文地址:https://www.stayed.cn/item/26032
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我