本文实例讲述了ThinkPHP3.2.2实现持久登录功能的方法。分享给大家供大家参考,具体如下:
实现持久登录,即用户在登录时,勾选了"记住我"之后,无论是否关闭浏览器,只要不退出登录,在指定的时间内始终保持登录状态(缺点是在另一台电脑上登录过后,之前那台电脑就不能继续保持登录状态)。
首先,持久登陆使用 cookie 实现,但是 cookie 中不能保存用户密码这样重要的信息,即使加密过。解决方案是在用户登录表中新建3个字段identifier:第二身份标识,token:永久登录标识,timeout:永久登录超时时间。
1
2
3
4
5
6
7
8
9
10
11
|
+ ------------+-------------+------+-----+---------+----------------+ | 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
<?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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
<?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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
< 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
< 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 > |
附:模块目录
希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。