在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初学者常见问题集合 修正版(21问答)
Mar 23 PHP
php类中private属性继承问题分析
Nov 01 PHP
探讨PHP中OO之静态关键字以及类常量的详解
Jun 07 PHP
destoon网站转移服务器后搜索汉字出现乱码的解决方法
Jun 21 PHP
PHP管理依赖(dependency)关系工具 Composer 安装与使用
Aug 18 PHP
php实现无限级分类
Dec 24 PHP
Symfony2函数用法实例分析
Mar 18 PHP
PHP实现动态执行代码的方法
Mar 25 PHP
php 魔术常量详解及实例代码
Dec 04 PHP
PHP执行shell脚本运行程序不产生core文件的方法
Dec 28 PHP
php 查找数组元素提高效率的方法详解
May 05 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检测useragent版本示例
2014/03/24 PHP
编写PHP脚本来实现WordPress中评论分页的功能
2015/12/10 PHP
php获取指定数量随机字符串的方法
2017/02/06 PHP
php 的多进程操作实践案例分析
2020/02/28 PHP
JavaScript实现页面实时显示当前时间的简单实例
2013/07/20 Javascript
如何设置iframe高度自适应在跨域情况下的可用方法
2013/09/06 Javascript
jquery无限级联下拉菜单简单实例演示
2015/11/23 Javascript
日常收集整理的JavaScript常用函数方法
2015/12/10 Javascript
jQuery实现验证年龄简单思路
2016/02/24 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
使用BootStrap实现用户登录界面UI
2016/08/10 Javascript
JavaScript职责链模式概述
2016/09/17 Javascript
Bootstrap4如何定制自己的颜色和风格
2018/02/26 Javascript
详解React项目的服务端渲染改造(koa2+webpack3.11)
2018/03/19 Javascript
JavaScript函数、闭包、原型、面向对象学习笔记
2018/09/06 Javascript
vue中的过滤器实例代码详解
2019/06/06 Javascript
移动端底部导航固定配合vue-router实现组件切换功能
2019/06/13 Javascript
JS数组属性去重并校验重复数据
2020/01/10 Javascript
微信小程序去除左上角返回键的实现方法
2020/03/06 Javascript
vue+animation实现翻页动画
2020/06/29 Javascript
js实现页面导航层级指示效果
2020/08/25 Javascript
在Python中操作列表之List.append()方法的使用
2015/05/20 Python
Python正则表达式经典入门教程
2017/05/22 Python
Python机器学习之决策树算法
2017/12/22 Python
python自动发送邮件脚本
2018/06/20 Python
Python可视化工具如何实现动态图表
2020/10/23 Python
用CSS3实现Win8风格的方格导航菜单效果
2013/04/10 HTML / CSS
盖尔斯工厂店:GUESS Factory
2020/01/21 全球购物
中英文自我评价常用句型
2013/12/19 职场文书
道路运输企业安全生产责任书
2014/07/28 职场文书
股东授权委托书范本
2014/09/13 职场文书
2015年清剿火患专项行动工作总结
2015/07/27 职场文书
Redis 配置文件重要属性的具体使用
2021/05/20 Redis
详解python的异常捕获
2022/03/03 Python
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技
聊聊配置 Nginx 访问与错误日志的问题
2022/05/25 Servers