在yii中新增一个用户验证的方法详解


Posted in PHP onJune 20, 2013

1.为什么要新增一个用户验证:
因为我要将网站后台和前台做在同一个yii的应用中.但是前台也包含有会员的管理中心.而这两个用户验证是完全不同的,所以需要两个不同登陆页面,要将用户信息保存在不同的cookie或session中.所以需要在一个应用中增加一个用户验证

2.yii的用户验证:
在自定义用户验证前,我们首先要弄清楚yii的验证和授权方式.
为了验证一个用户,我们需要定义一个有验证逻辑的验证类.在yii中这个类需要实现IUserIdentity接口,不同的类就可以实现不同的验证方 法.网站登陆一般需要验证的就是用户名和密码,yii提供了CUserIdentity类,这个类一般用于验证用户名和密码的类.继承后我们需要重写其中 的authenticate()方法来实现我们自己的验证方法.具体代码如下:
Php代码

class UserIdentity extends CUserIdentity  
{  
    private $_id;  
    public function authenticate()  
    {  
        $record=User::model()->findByAttributes(array('username'=>$this->username));  
        if($record===null)  
            $this->errorCode=self::ERROR_USERNAME_INVALID;  
        else if($record->password!==md5($this->password))  
            $this->errorCode=self::ERROR_PASSWORD_INVALID;  
        else 
        {  
            $this->_id=$record->id;  
            $this->setState('title', $record->title);  
            $this->errorCode=self::ERROR_NONE;  
        }  
        return !$this->errorCode;  
    }  
    public function getId()  
    {  
        return $this->_id;  
    }  
}

在用户登陆时则调用如下代码:
Php代码
// 使用提供的用户名和密码登录用户  
$identity=new UserIdentity($username,$password);  
if($identity->authenticate())  
    Yii::app()->user->login($identity);  
else 
    echo $identity->errorMessage;

用户退出时,则调用如下代码:
Php代码
// 注销当前用户  
Yii::app()->user->logout(); 
 其中的user是yii的一个components.需要在protected/config/main.php中定义

Php代码
'user'=>array(  
    // enable cookie-based authentication  
    'allowAutoLogin'=>true,  
        'loginUrl' => array('site/login'),  
),

这里我们没有指定user的类名.因为在yii中默认user为CWebUser类的实例.
我 们现在已经实现了用户的登陆验证和退出.但是现在无论是否登陆,用户都能访问所有的action,所以下一步我们要对用户访问进行授权.在yii里是通过 Access Control Filter即访问控制过滤器来实现用户授权的.我们看一下一个简单的带有访问控制的Controller:
Php代码
class AdminDefaultController extends CController  
{   
    public function filters()  
        {  
            return array('accessControl');  
        }  
        public function accessRules()  
        {  
            return array(  
                array(  
                    'allow',  
                    'users' => array('@'),  
                ),  
                array(  
                    'deny',  
                    'users' => array('*')  
                ),  
            );  
        }  
}

我们在filters方法中设置具体的filter.我们可以看到在filters方法返回的array里有accessControl参数,在CController类中有一个filterAccessControl方法:
Php代码
public function filterAccessControl($filterChain)  
{  
    $filter=new CAccessControlFilter;  
    $filter->setRules($this->accessRules());  
    $filter->filter($filterChain);  
}

在里面新建了一个CAccessControlFilter实例,并且在setRules时传入了accessRules()方法返回的参数.
$filter->filter($filterChain)则是继续调用其它filter.
而所有具体的授权规则则是定义在accessRules中:
Php代码
public function accessRules()  
    {  
        return array(  
            array('deny',  
                'actions'=>array('create', 'edit'),  
                'users'=>array('?'),  
            ),  
            array('allow',  
                'actions'=>array('delete'),  
                'roles'=>array('admin'),  
            ),  
            array('deny',  
                'actions'=>array('delete'),  
                'users'=>array('*'),  
            ),  
        );  
    }

具体规则参见yii的手册.
3.新增一个验证体系:
首先我们从CWebUser继承一个CAdminUser:
Php代码
class CAdminWebUser extends CWebUser  
{  
    public $loginUrl = array('admin/admin/login');  
}

我们需要把他放置到components中
如果是全局应用则通过protected/config/main.php的components小节:
Php代码
'user'=>array(  
    // enable cookie-based authentication  
        'class' => 'CAdminUser',  
    'allowAutoLogin'=>true,  
       'loginUrl' => array('site/login'),  
),

如果是在modules中则在模块类的init方法中添加如下代码:
Php代码
$this->setComponents(array(  
       'adminUser' => array(  
                'class' => 'CAdminWebUser',  
                'allowAutoLogin' => false,  
        )  
));

最后调用方式
Php代码
//全局应用  
Yii::app()->getComponent('adminUser');  
//在模块中  
Yii::app()->controller->module->getComponent('adminUser');

但仅仅这样还不够,我们还需要修改Controller的filter,我们需要自定义一个filter,来实现另一个用户的验证和授权
第一步自定义一个filter:
Php代码
class CAdminAccessControlFilter extends CAccessControlFilter  
{  
    protected function preFilter($filterChain)  
    {  
        $app=Yii::app();  
        $request=$app->getRequest();  
        $user = Yii::app()->controller->module->getComponent('adminUser');  
        $verb=$request->getRequestType();  
        $ip=$request->getUserHostAddress();          foreach($this->getRules() as $rule)  
        {  
            if(($allow=$rule->isUserAllowed($user,$filterChain->controller,$filterChain->action,$ip,$verb))>0) // allowed  
                break;  
            else if($allow<0) // denied  
            {  
                $this->accessDenied($user);  
                return false;  
            }  
        }  
        return true;  
    }  
}

再重写CController类的filterAccessController方法
Php代码
public function filterAccessControl($filterChain)  
{  
    $filter = new CAdminAccessControlFilter();  
    $filter->setRules($this->accessRules());  
    $filter->filter($filterChain);  
}  
//在这里我们使用自定义的filter类替换了原来的filter

OK,到这里我们就可以在此Controller的accessRules()中指定adminUser的授权了
PHP 相关文章推荐
PHP新手上路(十二)
Oct 09 PHP
数据库查询记录php 多行多列显示
Aug 15 PHP
PHP 分页原理分析,大家可以看看
Dec 21 PHP
php设计模式之观察者模式的应用详解
May 21 PHP
PHP批量生成静态HTML的简单原理和方法
Apr 20 PHP
javascript some()函数用法详解
Nov 13 PHP
PHP命名空间namespace用法实例分析
Sep 27 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
Nov 21 PHP
PHP中Notice错误常见解决方法
Apr 28 PHP
基于swoole实现多人聊天室
Jun 14 PHP
PHP实现的日历功能示例
Sep 01 PHP
tp5(thinkPHP5)框架连接数据库的方法示例
Dec 24 PHP
浅析Yii中使用RBAC的完全指南(用户角色权限控制)
Jun 20 #PHP
php中0,null,empty,空,false,字符串关系的详细介绍
Jun 20 #PHP
解析PHP中数组元素升序、降序以及重新排序的函数
Jun 20 #PHP
解析php中的fopen()函数用打开文件模式说明
Jun 20 #PHP
深入解析PHP内存管理之谁动了我的内存
Jun 20 #PHP
解析php中die(),exit(),return的区别
Jun 20 #PHP
有关PHP性能优化的介绍
Jun 20 #PHP
You might like
用PHP+MySql编写聊天室
2006/10/09 PHP
PHP数组游标实现对数组的各种操作详解
2016/01/26 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
event.keyCode键码值表 附只能输入特定的字符串代码
2009/05/15 Javascript
面向对象的javascript(笔记)
2009/10/06 Javascript
JavaScript 语法集锦 脚本之家基础推荐
2009/11/15 Javascript
multiSteps 基于Jquery的多步骤滑动切换插件
2011/07/22 Javascript
jquery插件lazyload.js延迟加载图片的使用方法
2014/02/19 Javascript
JavaScript动态创建link标签到head里的方法
2014/12/22 Javascript
jQuery中attr()方法用法实例
2015/01/05 Javascript
13个PHP函数超实用
2015/10/21 Javascript
jQuery validate+artdialog+jquery form实现弹出表单思路详解
2016/04/18 Javascript
JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
2016/05/16 Javascript
jQuery四种选择器使用及示例
2016/06/05 Javascript
js css实现垂直方向自适应的三角提示菜单
2016/06/26 Javascript
jquery实现数字输入框
2017/02/22 Javascript
JavaScript函数表达式详解及实例
2017/05/05 Javascript
nodejs 子进程正确的打开方式
2017/07/03 NodeJs
thinkjs 文件上传功能实例代码
2017/11/08 Javascript
vue组件(全局,局部,动态加载组件)
2018/09/02 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
微信小程序template模版的使用方法
2019/04/13 Javascript
过滤器vue.filters的使用方法实现
2019/09/18 Javascript
JS加载解析Markdown文档过程详解
2020/05/19 Javascript
python函数式编程学习之yield表达式形式详解
2018/03/25 Python
Python subprocess库的使用详解
2018/10/26 Python
win10环境下配置vscode python开发环境的教程详解
2019/10/16 Python
解决jupyter notebook import error但是命令提示符import正常的问题
2020/04/15 Python
Python实现发票自动校核微信机器人的方法
2020/05/22 Python
使用CSS3和Checkbox实现JQuery的一些效果
2015/08/03 HTML / CSS
介绍一下Java中标识符的命名规则
2014/02/03 面试题
校园报刊亭的创业计划书
2014/01/02 职场文书
致800米运动员广播稿
2014/02/16 职场文书
银行保安拾金不昧表扬稿
2015/05/05 职场文书
2015年数学教师工作总结
2015/05/20 职场文书
Redis实战之Lettuce的使用技巧详解
2022/12/24 Redis