文章目录
  1. 1. 起因
  2. 2. 自定义WebUser

起因

由于最近在做的一个网站中想把管理员跟普通用户分离开来,所以需要给所有的 用户添加一个admin,用来判断此用户是不是管理员。本来以为直接使用 Yii::app()->user->admin=1 就可以完成这个功能,结果发现会出错,看来不 能像python一样直接动态添加属性。所以就研究了一下Yii的CWebUser类和 CUserIdentity,得到如下解决方法。

自定义WebUser

在components目录中添加WebUser.php文件,内容如下,实现了admin参数的设定 和读取。

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
<?php
// 自定义用户类

class WebUser extends CWebUser {
// 获取admin值
public function getAdmin() {
if (($admin = $this->getState('__admin')) !== null)
return $admin;
else
return 0;
}
// 设置admin值
public function setAdmin($value) {
$this->setState('__admin', $value);
}
// 改变用户身份
protected function changeIdentity($id, $name, $states, $admin) {
Yii::app()->getSession()->regenerateID(true);
$this->setId($id);
$this->setName($name);
$this->setAdmin($admin);
$this->loadIdentityStates($states);
}
// 登陆
public function login($identity, $duration = 0) {
$id = $identity->getId();
$states = $identity->getPersistentStates();
if ($this->beforeLogin($id, $states, false)) {
$this->changeIdentity($id, $identity->getName() , $states, $identity->getAdmin());
if ($duration > 0) {
if ($this->allowAutoLogin) $this->saveToCookie($duration);
else throw new CException(Yii::t('yii', '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.', array(
'{class}' => get_class($this)
)));
}
$this->afterLogin(false);
}

return !$this->getIsGuest();
}
}

在config/main.php这个配置文件中加入或更改成如下代码

1
2
3
4
5
6
<?php
'user' => array(
'allowAutoLogin' => true,
// 主要是设置这个自定义的class
'class' => "WebUser",
) ,

然后添加一个components/AdminIdentity.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
<?php
class AdminIdentity extends CUserIdentity {
public $id;
public $admin=0;

public function authenticate() {
// 验证用户名是否在admins表里面存在
$admin = Admin::model()->findByAttributes(array(
'username' => $this->username
));
// 没有这个用户则返回用户名错误
if ($admin == null)
{
$this->errorCode = self::ERROR_USERNAME_INVALID;
// 验证密码
} elseif ($admin->password != md5($this->password)) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
} else {
$this->username = $admin->username;
$this->id = $admin->id;
// 设置为管理员
$this->admin = 1;
$admin->last_login_time = $admin->this_login_time;
$admin->this_login_time = time();
$admin->last_login_ip = $admin->this_login_ip;
$admin->this_login_ip = Yii::app()->getRequest()->userHostAddress;
$admin->save();
$this->errorCode = self::ERROR_NONE;
}

return !$this->errorCode;
}
public function getId() {

return $this->id;
}

// 获取admin状态 0: 不是管理员(默认值) 1:管理员
public function getAdmin() {
return $this->admin;
}
}

用于普通用户验证的UserIdentity代码跟上面的管理员类似,只是默认的 admin值变成0。然后在filters目录中添加AdminFilter.php文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// 管理中心过滤器,过滤掉不是管理员的用户
class AdminFilter extends CFilter {
// 在action之前的过滤器
protected function preFilter($filterChain) {
if (Yii::app()->user->admin == 0) {
// 调用控制器的redirect函数,跳转到登陆页面
$filterChain->controller->redirect(Yii::app()->user->loginUrl);
Yii::app()->end();

return false;
}

return true; // false if the action should not be executed

}
}

tip

这个filters目录是我自己新建的,需要在main.php添加对应的配置。

最后就是在components文件夹里面添加一个AdminController.php。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// 后台管理的控制器
class AdminController extends Controller {
// 设置默认layout
public $layout = 'admin';
public function filters() {
// 设置验证不过时的跳转地址
Yii::app()->user->loginUrl = $this->createUrl('admin/login/index');
// 加载管理中心过滤器

return array(
array(
'AdminFilter'
)
);
}
}

然后只要是管理员的全部继承自这个AdminController,这样就能过滤掉全部的 普通用户了。这种方法只是普通的用户过滤,如果需要详细的权限设置可以使用 一下Yii的rbac。这里就不作详细介绍了。

文章目录
  1. 1. 起因
  2. 2. 自定义WebUser