您的位置:首页 > 编程语言 > PHP开发

Yii中处理前后台登录新方法

2016-03-28 11:25 597 查看
因为最近在做一个项目涉及到前后台登录问题,我是把后台作为一个模块(Module)来处理的。我看很多人放两个入口文件index.php和admin.php,然后分别指向前台和后台。这种方法固然很好,可以将前后台完全分离,但我总觉得这种方式有点牵强,这和两个应用啥区别?还不如做两个App用一个framework更好。而且Yii官方后台使用方法也是使用Module的方式。但是Moudle的方式有一个很头疼的问题,就是在使用Cwebuser登录时会出现前后台一起登录一起退出的问题,这显然是不合理的。我纠结了很久才找到下文即将介绍的方法,当然,很多也是参考别人的,自己稍作了改动。我一开始的做法是在后台登录时设置一个isadmin的session,然后再前台登录时注销这个session,这样做只能辨别是前台登录还是后台登录,但做不到前后台一起登录,也即前台登录了后台就退出了,后台登录了前台就退出了。出现这种原因的根本原因是我们使用了同一个Cwebuser实例,不能同时设置前后台session,要解决这个问题就要将前后台使用不同的Cwebuser实例登录。下面是我的做法,首先看protected->config->main.php里对前台user(Cwebuser)的配置:

1
'user'
=>
array
(
2
'class'
=>
'WebUser'
,
//这个WebUser是继承CwebUser,稍后给出它的代码
3
'stateKeyPrefix'
=>
'member'
,
//这个是设置前台session的前缀
4
'allowAutoLogin'
=>true,
//这里设置允许cookie保存登录信息,一边下次自动登录
5
),
在你用Gii生成一个admin(即后台模块名称)模块时,会在module->admin下生成一个AdminModule.php文件,该类继承了CWebModule类,下面给出这个文件的代码,关键之处就在该文件,望大家仔细研究:

01
<?php
02
03
class
AdminModule
extends
CWebModule
04
{
05
public
function

init()
06
{
07
//thismethodiscalledwhenthemoduleisbeingcreated
08
//youmayplacecodeheretocustomizethemoduleortheapplication
09
parent::init();
//这步是调用main.php里的配置文件
10
//importthemodule-levelmodelsandcomponen
11
$this
->setImport(
array
(
12
'admin.models.*'
,
13
'admin.components.*'
,
14
));
15
//这里重写父类里的组件
16
//如有需要还可以参考API添加相应组件
17
Yii::app()->setComponents(
array
(
18
'errorHandler'
=>
array
(
19
'class'
=>
'CErrorHandler'
,
20
'errorAction'
=>
'admin/default/error'
,
21
),
22
'admin'
=>
array
(
23
'class'
=>
'AdminWebUser'
,
//后台登录类实例
24
'stateKeyPrefix'
=>
'admin'
,
//后台session前缀
25
'loginUrl'
=>Yii::app()->createUrl(
'admin/default/login'
),
26
),
27
),false);
28
//下面这两行我一直没搞定啥意思,貌似CWebModule里也没generatorPaths属性和findGenerators()方法
29
//$this->generatorPaths[]='admin.generators';
30
//$this->controllerMap=$this->findGenerators();
31
}
32
public
function

beforeControllerAction(
$controller
,
$action
){
33
if
(parent::beforeControllerAction(
$controller
,
$action
)){
34
$route
=
$controller
->id.
'/'
.
$action
->id;
35
if
(!
$this
->allowIp(Yii::app()->request->userHostAddress)&&
$route
!==
'default/error'
)
36
throw
new

CHttpException(403,
"Youarenotallowedtoaccessthispage."
);
37
$publicPages
=
array
(
38
'default/login'
,
39
'default/error'
,
40
);
41
if
(Yii::app()->user->isGuest&&!in_array(
$route
,
$publicPages
))
42
Yii::app()->user->loginRequired();
43
else
44
return
true;
45
}
46
return
false;
47
}
48
protected
function

allowIp(
$ip
)
49
{
50
if
(
empty
(
$this
->ipFilters))
51
return
true;
52
foreach
(
$this
->ipFilters
as

$filter
)
53
{
54
if
(
$filter
===
'*'
||
$filter
===
$ip
||((
$pos
=
strpos
(
$filter
,
'*'
))!==false
&&!
strncmp
(
$ip
,
$filter
,
$pos
)))
55
return
true;
56
}
57
return
false;
58
}
59
}
60
?>
AdminModule的init()方法就是给后台配置另外的登录实例,让前后台使用不同的CWebUser,并设置后台session前缀,以便与前台session区别开来(他们同事存在$_SESSION这个数组里,你可以打印出来看看)。

这样就已经做到了前后台登录分离开了,但是此时你退出的话你就会发现前后台一起退出了。于是我找到了logout()这个方法,发现他有一个参数$destroySession=true,原来如此,如果你只是logout()的话那就会将session全部注销,加一个false参数的话就只会注销当前登录实例的session了,这也就是为什么要设置前后台session前缀的原因了,下面我们看看设置了false参数的logout方法是如何注销session的:

01
/**
02
*Clearsalluseridentityinformationfrompersistentstorage.
03
*Thiswillremovethedatastoredvia{@linksetState}.
04
*/
05
public
function
clearStates()
06
{
07
$keys
=
array_keys
(
$_SESSION
);
08
$prefix
=
$this
->getStateKeyPrefix();
09
$n
=
strlen
(
$prefix
);
10
foreach
(
$keys
as

$key
)
11
{
12
if
(!
strncmp
(
$key
,
$prefix
,
$n
))
13
unset(
$_SESSION
[
$key
]);
14
}
15
}
看到没,就是利用匹配前缀的去注销的。

到此,我们就可以做到前后台登录分离,退出分离了。这样才更像一个应用,是吧?嘿嘿…

差点忘了说明一下:

1
Yii::app()->user
//前台访问用户信息方法
2
Yii::app()->admin
//后台访问用户信息方法
不懂的仔细看一下刚才前后台CWebUser的配置。

附件1:WebUser.php代码:

01
<?php
02
class

WebUser
extends
CWebUser
03
{
04
public
function

__get(
$name
)
05
{
06
if
(
$this
->hasState(
'__userInfo'
))
{
07
$user
=
$this
->getState(
'__userInfo'
,
array
());
08
if
(isset(
$user
[
$name
]))
{
09
return
$user
[
$name
];
10
}
11
}
12
13
return
parent::__get(
$name
);
14
}
15
16
public
function

login(
$identity
,
$duration
){
17
$this
->setState(
'__userInfo'
,
$identity
->getUser());
18
parent::login(
$identity
,
$duration
);
19
}
20
}
21
22
?>
附件2:AdminWebUser.php代码

01
<?php
02
class

AdminWebUser
extends
CWebUser
03
{
04
public
function

__get(
$name
)
05
{
06
if
(
$this
->hasState(
'__adminInfo'
))
{
07
$user
=
$this
->getState(
'__adminInfo'
,
array
());
08
if
(isset(
$user
[
$name
]))
{
09
return
$user
[
$name
];
10
}
11
}
12
13
return
parent::__get(
$name
);
14
}
15
16
public
function

login(
$identity
,
$duration
){
17
$this
->setState(
'__adminInfo'
,
$identity
->getUser());
18
parent::login(
$identity
,
$duration
);
19
}
20
}
21
22
?>
附件三:前台UserIdentity.php代码

01
<?php
02
03
/**
04
*UserIdentityrepresentsthedataneededtoidentityauser.
05
*Itcontainstheauthenticationmethodthatchecksiftheprovided
06
*datacanidentitytheuser.
07
*/
08
class

UserIdentity
extends
CUserIdentity
09
{
10
/**
11
*Authenticatesauser.
12
*Theexampleimplementationmakessureiftheusernameandpassword
13
*areboth'demo'.
14
*Inpracticalapplications,thisshouldbechangedtoauthenticate
15
*againstsomepersistentuseridentitystorage(e.g.database).
16
*@returnbooleanwhetherauthenticationsucceeds.
17
*/
18
public
$user
;
19
public
$_id
;
20
public
$username
;
21
public
function

authenticate()
22
{
23
$this
->errorCode=self::ERROR_PASSWORD_INVALID;
24
$user
=User::model()->find(
'username=:username'
,
array
(
':username'
=>
$this
->username));
25
if
(
$user
)
26
{
27
$encrypted_passwd
=trim(
$user
->password);
28
$inputpassword
=trim(md5(
$this
->password));
29
if
(
$inputpassword
===
$encrypted_passwd
)
30
{
31
$this
->errorCode=self::ERROR_NONE;
32
$this
->setUser(
$user
);
33
$this
->_id=
$user
->id;
34
$this
->username=
$user
->username;
35
//if(isset(Yii::app()->user->thisisadmin))
36
//unset(Yii::app()->user->thisisadmin);
37
}
38
else
39
{
40
$this
->errorCode=self::ERROR_PASSWORD_INVALID;
41
42
}
43
}
44
else
45
{
46
$this
->errorCode=self::ERROR_USERNAME_INVALID;
47
}
48
49
unset(
$user
);
50
return
!
$this
->errorCode;
51
52
}
53
public
function

getUser()
54
{
55
return
$this
->user;
56
}
57
58
public
function

getId()
59
{
60
return
$this
->_id;
61
}
62
63
public
function

getUserName()
64
{
65
return
$this
->username;
66
}
67
68
public
function

setUser(CActiveRecord
$user
)
69
{
70
$this
->user=
$user
->attributes;
71
}
72
}
附件四:后台UserIdentity.php代码

01
<?php
02
03
/**
04
*UserIdentityrepresentsthedataneededtoidentityauser.
05
*Itcontainstheauthenticationmethodthatchecksiftheprovided
06
*datacanidentitytheuser.
07
*/
08
class

UserIdentity
extends
CUserIdentity
09
{
10
/**
11
*Authenticatesauser.
12
*Theexampleimplementationmakessureiftheusernameandpassword
13
*areboth'demo'.
14
*Inpracticalapplications,thisshouldbechangedtoauthenticate
15
*againstsomepersistentuseridentitystorage(e.g.database).
16
*@returnbooleanwhetherauthenticationsucceeds.
17
*/
18
public
$admin
;
19
public
$_id
;
20
public
$username
;
21
public
function

authenticate()
22
{
23
$this
->errorCode=self::ERROR_PASSWORD_INVALID;
24
$user
=Staff::model()->find(
'username=:username'
,
array
(
':username'
=>
$this
->username));
25
if
(
$user
)
26
{
27
$encrypted_passwd
=trim(
$user
->password);
28
$inputpassword
=trim(md5(
$this
->password));
29
if
(
$inputpassword
===
$encrypted_passwd
)
30
{
31
$this
->errorCode=self::ERROR_NONE;
32
$this
->setUser(
$user
);
33
$this
->_id=
$user
->id;
34
$this
->username=
$user
->username;
35
//Yii::app()->user->setState("thisisadmin","true");
36
}
37
else
38
{
39
$this
->errorCode=self::ERROR_PASSWORD_INVALID;
40
41
}
42
}
43
else
44
{
45
$this
->errorCode=self::ERROR_USERNAME_INVALID;
46
}
47
48
unset(
$user
);
49
return
!
$this
->errorCode;
50
51
}
52
public
function

getUser()
53
{
54
return
$this
->admin;
55
}
56
57
public
function

getId()
58
{
59
return
$this
->_id;
60
}
61
62
public
function

getUserName()
63
{
64
return
$this
->username;
65
}
66
67
public
function

setUser(CActiveRecord
$user
)
68
{
69
$this
->admin=
$user
->attributes;
70
}
71
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: