在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+APACHE实现用户论证的方法
Oct 09 PHP
PHP防注入安全代码
Apr 09 PHP
php使用mb_check_encoding检查字符串在指定的编码里是否有效
Nov 07 PHP
ThinkPHP标签制作教程
Jul 10 PHP
PHP中读取文件的8种方法和代码实例
Aug 05 PHP
ThinkPHP后台首页index使用frameset时的注意事项分析
Aug 22 PHP
php实现每天自动变换随机问候语的方法
May 12 PHP
php文件上传类完整实例
May 14 PHP
PHP打印输出函数汇总
Aug 28 PHP
php获取服务器操作系统相关信息的方法
Oct 08 PHP
PHP 中 var_export、print_r、var_dump 调试中的区别
Jun 19 PHP
PHP大文件分片上传的实现方法
Oct 28 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
Apache2 httpd.conf 中文版
2006/11/17 PHP
php从文件夹随机读取文件的方法
2015/06/01 PHP
PHP使用CURL模拟登录的方法
2015/07/08 PHP
php实现curl模拟ftp上传的方法
2015/07/29 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
表单(FORM)的一些实用效果代码
2007/03/25 Javascript
JS获取父节点方法
2009/08/20 Javascript
JS中图片缓冲loading技术的实例代码
2013/08/29 Javascript
jQuery实现伸展与合拢panel的方法
2015/04/30 Javascript
IE浏览器下PNG相关功能
2015/07/05 Javascript
jQuery仿淘宝网产品品牌隐藏与显示效果
2015/09/01 Javascript
jQuery ajax时间差导致的变量赋值问题分析
2016/01/22 Javascript
jQuery视差滚动效果网页实现方法经验总结
2016/09/29 Javascript
简单实现js浮动框
2016/12/13 Javascript
jQuery使用正则表达式替换dom元素标签用法示例
2017/01/16 Javascript
xmlplus组件设计系列之路由(ViewStack)(7)
2017/05/02 Javascript
详解利用 Express 托管静态文件的方法
2017/09/18 Javascript
使用vue实现grid-layout功能实例代码
2018/01/05 Javascript
vue初尝试--项目结构(推荐)
2018/01/30 Javascript
p5.js入门教程之键盘交互
2018/03/19 Javascript
vue-cli中vue本地实现跨域调试接口
2019/01/16 Javascript
layui 上传图片 返回图片地址的方法
2019/09/26 Javascript
[04:39]显微镜下的DOTA2第十三期—Pis卡尔个人秀
2014/04/04 DOTA
python二分法实现实例
2013/11/21 Python
python 杀死自身进程的实现方法
2019/07/01 Python
python对常见数据类型的遍历解析
2019/08/27 Python
详解python中的模块及包导入
2019/08/30 Python
win10环境下配置vscode python开发环境的教程详解
2019/10/16 Python
浅谈Django2.0 加xadmin踩的坑
2019/11/15 Python
Python3标准库之threading进程中管理并发操作方法
2020/03/30 Python
领导证婚人证婚词
2014/01/13 职场文书
办公室综合文员岗位职责范本
2014/02/13 职场文书
《恐龙》教学反思
2014/04/27 职场文书
高一学年自我鉴定范文(3篇)
2014/09/26 职场文书
财务部会计岗位职责
2015/02/03 职场文书
SpringBoot详解执行过程
2022/07/15 Java/Android