Yii2 认证实现原理和示例
Posted 小帅豹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Yii2 认证实现原理和示例相关的知识,希望对你有一定的参考价值。
Yii的用户认证分为两个部分,一个是User组件,负责管理用户认证状态的,包括登录,登出,检测当前登录状态等,源文件位于vender/yiisoft/yii2/web/User.php。另一个是实现接口IdentityInterface的模型,同时必须继承ActiveRecord,当用户登录注册时,组件User会通过模型中的接口方法,对用户进行验证。
对于用户状态切换主要通过switchIdentity方法实现的,比如注册后,用户登录时,会用到User组件中的switchIdentity方法,如下:
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
|
/** * Switches to a new identity for the current user. * * When [[enableSession]] is true, this method may use session and/or cookie to store the user identity information, * according to the value of `$duration`. Please refer to [[login()]] for more details. * * This method is mainly called by [[login()]], [[logout()]] and [[loginByCookie()]] * when the current user needs to be associated with the corresponding identity information. * * @param IdentityInterface|null $identity the identity information to be associated with the current user. * If null, it means switching the current user to be a guest. * @param integer $duration number of seconds that the user can remain in logged-in status. * This parameter is used only when `$identity` is not null. */ public function switchIdentity( $identity , $duration = 0) { $this ->setIdentity( $identity ); if (! $this ->enableSession) { return ; } /* Ensure any existing identity cookies are removed. */ if ( $this ->enableAutoLogin) { $this ->removeIdentityCookie(); } $session = Yii:: $app ->getSession(); if (!YII_ENV_TEST) { $session ->regenerateID(true); } $session ->remove( $this ->idParam); $session ->remove( $this ->authTimeoutParam); if ( $identity ) { $session ->set( $this ->idParam, $identity ->getId()); if ( $this ->authTimeout !== null) { $session ->set( $this ->authTimeoutParam, time() + $this ->authTimeout); } if ( $this ->absoluteAuthTimeout !== null) { $session ->set( $this ->absoluteAuthTimeoutParam, time() + $this ->absoluteAuthTimeout); } if ( $duration > 0 && $this ->enableAutoLogin) { $this ->sendIdentityCookie( $identity , $duration ); } } } |
如果写入identity为null,则将用户状态设置为离线,如果不是null,而是模型实例,该方法会将用户模型的id值写入session中,用户打开新页面时,只需下面的方法就可以判断是否已经登录。
1
2
|
//已登录返回true Yii:: $app ->user->isGuest |
访问user组件的isGuest属性,会通过魔术方法,调用User组件中的getIsGuest方法
1
2
3
4
5
6
7
8
9
|
/** * Returns a value indicating whether the user is a guest (not authenticated). * @return boolean whether the current user is a guest. * @see getIdentity() */ public function getIsGuest() { return $this ->getIdentity() === null; } |
方法又调用getIdentity()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/** * Returns the identity object associated with the currently logged-in user. * When [[enableSession]] is true, this method may attempt to read the user\'s authentication data * stored in session and reconstruct the corresponding identity object, if it has not done so before. * @param boolean $autoRenew whether to automatically renew authentication status if it has not been done so before. * This is only useful when [[enableSession]] is true. * @return IdentityInterface|null the identity object associated with the currently logged-in user. * `null` is returned if the user is not logged in (not authenticated). * @see login() * @see logout() */ public function getIdentity( $autoRenew = true) { if ( $this ->_identity === false) { if ( $this ->enableSession && $autoRenew ) { $this ->_identity = null; $this ->renewAuthStatus(); } else { return null; } } return $this ->_identity; } |
当session启用时,通过renewAuthStatus()更新新用户状态
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
|
/** * Updates the authentication status using the information from session and cookie. * * This method will try to determine the user identity using the [[idParam]] session variable. * * If [[authTimeout]] is set, this method will refresh the timer. * * If the user identity cannot be determined by session, this method will try to [[loginByCookie()|login by cookie]] * if [[enableAutoLogin]] is true. */ protected function renewAuthStatus() { $session = Yii:: $app ->getSession(); $id = $session ->getHasSessionId() || $session ->getIsActive() ? $session ->get( $this ->idParam) : null; if ( $id === null) { $identity = null; } else { /* @var $class IdentityInterface */ $class = $this ->identityClass; $identity = $class ::findIdentity( $id ); } $this ->setIdentity( $identity ); if ( $identity !== null && ( $this ->authTimeout !== null || $this ->absoluteAuthTimeout !== null)) { $expire = $this ->authTimeout !== null ? $session ->get( $this ->authTimeoutParam) : null; $expireAbsolute = $this ->absoluteAuthTimeout !== null ? $session ->get( $this ->absoluteAuthTimeoutParam) : null; if ( $expire !== null && $expire < time() || $expireAbsolute !== null && $expireAbsolute < time()) { $this ->logout(false); } elseif ( $this ->authTimeout !== null) { $session ->set( $this ->authTimeoutParam, time() + $this ->authTimeout); } } if ( $this ->enableAutoLogin) { if ( $this ->getIsGuest()) { $this ->loginByCookie(); } elseif ( $this ->autoRenewCookie) { $this ->renewIdentityCookie(); } } } |
该方法主要通过session取出用户id,然后通过id获取用户模型实例,然后使用实例进行登录,和更新认证过期时间。
下面实现一个常用的用户注册登录功能模块,用户只有登录后才可以进入home页面
User模型:
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
|
<?php /** * Created by PhpStorm. * User: zhenbao * Date: 16/10/17 * Time: 下午4:14 */ namespace app\\models; use Yii; use yii\\web\\IdentityInterface; use yii\\db\\ActiveRecord; class User extends ActiveRecord implements IdentityInterface { const LOGIN = "login" ; const REGISTER = "register" ; { return [ self::LOGIN => [ \'username\' , \'password\' ], self::REGISTER => [ \'username\' , \'password\' ] ]; } public static function tableName() { return "user" ; } public static function findIdentity( $id ) { return static ::findOne( $id ); } public static function findIdentityByAccessToken( $token , $type = null) { return static ::findOne([ \'accessToken\' => $token ]); } public function getId() { return $this -> id; } public function getAuthKey() { return $this -> authKey; } public function validateAuthKey( $authKey ) { return $this -> getAuthKey() === $authKey ; } public static function findIdentityByUsername( $username ) { return static ::findOne([ \'username\' => $username ]); } public function validatePassword( $password ) { return $this -> password === sha1( $password ); } public function setPassword() { $this -> password = sha1( $this -> password); return true; } public function beforeSave( $insert ) { if (parent::beforeSave( $insert )) { if ( $this -> isNewRecord) { $this -> authKey = Yii:: $app -> security -> generateRandomString(); } return true; } return false; } } |
控制器:
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
105
106
107
108
109
110
111
|
<?php namespace app\\controllers; use Yii; use yii\\web\\Controller; use app\\models\\User; use yii\\web\\Cookie; class UserController extends Controller { /**默认方法为home方法 * @var string */ public $defaultAction = \'home\' ; /**用户登录,当已经登录直接跳转home页面, * 否则,查看是否有访问accessToken,如果有使用accessToken登录,如果accessToken无效则删除accessToken然后返回到登录界面 * 如果没有accessToken则使用用户的登录密码登录,验证成功后,查看是否选择了记住我,有则生成accessToken,下次直接使用accessToken登录 * 登录失败,返回到登录界面重新登录。 * @return string|\\yii\\web\\Response */ public function actionLogin() { 以上是关于Yii2 认证实现原理和示例的主要内容,如果未能解决你的问题,请参考以下文章
|