上次研究Yii框架写到了要完成用户登录系统.此次接着上次的写.php
参考官方权威指南和参考手册,外加各类博客文章.历尽千辛万苦,数遍天上滴星星.完成了后台用户登陆.这里用到了YII框架的前端
CUserIdentity类. -------实现基于用户名和密码的验证.数据库
CWebForm类 ---------登陆表单数组
CController类 ------控制器的基础类cookie
CWebUser类 ------储存用户的持久身份信息session
第一步:分离用户系统app
要想实现用户登陆.先研究一下YII的登陆流程.YII框架提供和颇有用的登陆辅助类和用户身份类供咱们使用.上次说到admin使用模块来开发管理后台.那么要实现后台与前台的相对独立.首先要实现先后台两套用户系统.YII的CUserIdentity类是用来提供用户身份相关的存储,验证等操做.这个类在默认的配置文件main.php里面有配置.就是配置文件里面components下面的user.查看手册能够看到这几行配置就是配置的CUserIdentity的一个实例.之后能够经过Yii::app()->user来访问这个实例.调用其中的方法.可是我想要两套用户系统.一套用做网站的前台登陆.一套用做管理的后台登陆.那么就要修改这个配置.用户系统是基于CUserIdentity类.那么若是我想要两套用户系统,就要有两个CUserIdentity的实例.也能够有两个CUserIdentity的子类.这样也可以实现用户系统的分离.我把其中用做前台登陆的类叫作WebUsers类.这个类放在网站根目录下的components下面放置一个Webusers.php文件.里面只写明class WebUsers extends CWebUser{}就能够了.当我之后想修改网站用户的一些基础属性.只须要修改这个类就成了.另一个类我放在admin模块下的components下面.同上面的同样只写明class AdminUsers extends CWebUser{}就能够了.在最后我在main里面配置一下.框架
修改原来user的声明改为如下的样子yii
'components'=>array( 'user'=>array( 'class'=>'WebUsers', 'stateKeyPrefix'=>'user',//设置前台session前缀 'allowAutoLogin'=>true, ), 'admin'=>array( // enable cookie-based authentication 'class'=>'AdminUsers', 'stateKeyPrefix'=>'admin',//设置后台session前缀 'allowAutoLogin'=>false, 'loginUrl' =>array('/admin/adminuser/login'), ),
以前上文说过.这个配置数组是用来配置类的.也就是说我分别对前台和后台的两个用于保存网站用户的实例进行了配置.通过这样的配置.我就可以经过Yii::app()->user访问到网站用户的相关属性和调用相关的方法.而经过Yii::app()->admin来访问网站后台管理用户的相关属性,并调用相关的方法.网站
第二步:完成控制器.
分离完了用户系统.就要写控制器了.由于CMS系统须要验证用户身份.也就是说没有正确的帐号密码是不容许进行任何操做的.换个逻辑讲就是说在模块下的控制器的任何方法都应该在权限验证经过的状况下才能被执行.为了可以实现这个目的.我写了一个后台控制器的基础类,全部用做后台操做的控制器都继承自此控制器.这个控制器的名称我给定义成了AdminController.它继承自Ccontroller.我把这个类的文件存储在components下面,这样就会被模块的init方法自动导入进来.我能够经过手册发如今Ccontroller里面有一个方法叫作beforeAction().我只须要重写这个方法.在全部action执行以前验证用户身份.若是用户身份不合法.就直接引导到登陆页面上去.这个是咱们的实现思想.
小插曲:验证码.
想作登陆,那么验证码这个关键的东西是不可以少的.在YII的框架中有提供验证码.可是使用起来比较让人费解.它说要实现验证码.咱们须要重写控制器中的actions方法.完成一个继承自CCaptchaAction的action而且要求这个继承来的方法名字必须是captcha.这里我没有深刻的研究,参考yii框架自动生成的联系页面上验证码的生成.我写了验证码.固然.验证码能够进行配置.只须要配置数组便可.
完成上述步骤后.个人后台管理用到的基础控制器就完成了.代码是下面这个样子的:
class AdminController extends CController { public $pageTitle="后台管理"; /** * @var string the default layout for the controller view. Defaults to '//layouts/column1', * meaning using a single column layout. See 'protected/views/layouts/column1.php'. */ public $layout='application.modules.admin.views.layouts.admin'; /** * @var array context menu items. This property will be assigned to {@link CMenu::items}. */ public $menu=array(); /** * @var array the breadcrumbs of the current page. The value of this property will * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links} * for more details on how to specify this property. */ public $breadcrumbs=array(); public function actions(){ return array( 'captcha'=>array( 'class'=>'CCaptchaAction', 'backColor'=>0xFFFFFF, ),); } protected function beforeAction($action){ if(Yii::app()->admin->isGuest&&$action->getId()!='login'&&$action->getId()!='captcha'){ $this->redirect(Yii::app()->admin->loginUrl); } return parent::beforeAction($action); } }
说一下这个beforeAction 第一行.咱们判断咱们以前声明的后台用户体系中的当前用户是否是来宾用户.而且判断当前的Action是否是为login或者captcha,也就是当前是否是在登陆或者生成验证码.由于对于没有登陆的用户,若是不容许登陆操做和生成验证码操做就没办法完成登陆. 第二行.若是条件成立.也就是说当前的用户没有登陆.那么咱们就调用控制器里面的重定向方法,将访问定向到咱们以前再用户体系中声明的loginUrl去.最后一行.若是咱们的用户登陆了.那么咱们就调用父类的这个方法.实际上父类的方法里面是直接去执行action了.
好了,个人基础控制器完成了,在这里咱们定义了验证码,控制了用户登陆.接下来我就要写后台用户的第一个控制器了,用户控制器.里面要实现的方法大概有(还没想好),用户登陆,用户基本信息获取.用户登出.显示登陆后台的首页.再想到再添加.因而完成了第一个控制器.AdminUserController,具体代码以下:
class AdminuserController extends AdminController { public function actionIndex() { $this->render('index'); } public function actionLogin() { $model=new AdminLoginForm; if(isset($_POST['AdminLoginForm'])) { $model->attributes=$_POST['AdminLoginForm'];//将用户输入块赋值给AdminLoginForm的实例 if($r = $model->validate()) { // form inputs are valid, do something here $this->actionIndex();//若登录成功则显示首页 //$this->renderPartial('login',array('model'=>$model)); return; } } $this->renderPartial('login',array('model'=>$model)); } public function actionLogout(){ Yii::app()->admin->logout(); $this->actionLogin(); } }
代码贴出来了,先别着急看.这里面的actionLogin先不用去理解.我定义了三个动做.分别是login,logout,index,还有一个从父类继承过来的captcha.分别用来登陆,登出,显示首页和显示验证码.
第三步,创建模型.
yii有很好的抽象结构.将数据抽象成两种模式,一种是用做表单的,这样的数据不被持久化保存.因而有表单模型.另一种是用来抽象数据库的模型.这种数据会被保存到数据库里面.第二种模型里面封装了数据库的增删改查的方法.官方叫作CActiveRecord,咱们能够理解为第二种模型为数据模型.第一种模型为表单模型.
表单模型,故名思议就是对表单的一个抽象.这个模型里面定义了表单的各个属性和字段.定义了表单的验证规则.等等.当渲染一个表单的时候其实是生成了一个表单模型的实例.当咱们填写一个表单并提交的时候实际上完成的操做应该是把用户输入的数据用来填充这个模型.并保证用户填充的数据可以知足这里的验证规则.也就是说咱们对表单的操做实际上就是对这个表单模型实例的操做.按照Yii框架的设计原则,咱们的表单模型都应该集成自表单模型的基类.而数据模型都应该集成自数据模型的基类.这两个基类分别是 CFormModel,CActiveRecord.
拿咱们的登陆表单来讲.咱们的登陆表单继承自CFormModel,里面有几个属性.分别是用户名.密码.验证码.有一个方法,这个方法经过提交表单来收集用户输入并用已经定义的规则来比对用户输入.若是知足,就将用户输入赋值给表单模型实例的相应属性上,若是不知足就写入错误信息.(这个方法的名字叫作validate,是从CFormModel继承过来的//是用来验证的.)
数据模型.对应数据表的模型.能够理解为咱们把数据库里面某一张表抽象为一个模型.这个表里面的每一行就是这个模型的一个实例.当咱们执行这个数据模型的增删改查操做的时候,实际上就是对这个表的操做.而转换成面向对象的思想.咱们就是在操做着数据对象.还拿咱们的后台管理用户系统来讲.咱们须要实现对于后台用户表的抽象.因而咱们有了一个后台用户表的数据模型类.继承自CActiveRecord.(能够用GII生成).我是用Gii生成的.
个人登录表单模型以下:
<?php /** * ContactForm class. * ContactForm is the data structure for keeping * contact form data. It is used by the 'contact' action of 'SiteController'. */ class AdminLoginForm extends CFormModel { public $username; public $password; public $verifyCode;//验证码 private $_adminUserIdentity;//这个变量其实是基于用户名和密码验证的类的实例 /** * Declares the validation rules. */ public function rules() { return array( array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()), //当没有开启GD库拓展的时候容许验证码为空 array('username, password','required'), //用户名密码不能为空 // verifyCode needs to be entered correctly array('password', 'check_user'),//定义password须要使用该模型中的check_user方法来验证. ); } public function attributeLabels() { return array( 'username'=>'用户名', 'password'=>'密码', 'verifyCode'=>'验证码', ); } public function check_user($attribute,$params) { $this->_adminUserIdentity = new AdminUserIdentity($this->username,$this->password); $res = $this->_adminUserIdentity->authenticate();
//调用authenticate方法来验证用户提交的信息与数据库里面存储的信息是否一致. if($res == true){ Yii::app()->admin->login($this->_adminUserIdentity); return true; }else{ return false; } } }
第四步,理清逻辑.
先看看咱们手里有什么,
有AdminuserController控制器.
有在main.php里面声明的admin用户体系,其实是CWebUser的一个实例.
基于用户密码来验证的AdminUserIdentity.
有loginform的表单模型.(能够用gii来创建)
有admin_user数据表的数据模型.(能够用gii来创建)
固然,咱们还要有一张存储用户数据的数据表.这个要本身在数据库里面创建了.这个就不写出来了.
咱们须要一个可以渲染管理后台首页的视图.可能还要写一些layout.
还少什么:
少一个登陆界面的视图.
那就来创建一个登陆界面的视图.在yii权威指南里面能够找到使用表单那个章节.里面介绍了表单助手类的使用.这里我就再也不说了.想要在前端展现验证码.能够参考例子程序.实际上<?php $this->widget('CCaptcha'); ?>就可以完成验证码的图片输出.this指的是控制器的实例,而widget值得是渲染一个挂件.当传递进入的参数为CCaptcha时就可以直接生成一个验证码.
上面提到的还有个人后台管理用户的用户体系文件,放上来以下:
<?php class AdminUserIdentity extends CUserIdentity { private $_id; public function authenticate() { $record = AdminUser::model()->findByAttributes(array('username'=>$this->username)); if($record===null) { $this->errorMessage = '用户名不存在'; $this->errorCode=true; } else if($record->password!==md5($this->password)) { $this->errorMessage = '密码不正确'; $this->errorCode=true; } else { $this->_id=$record->id; $this->setState('title', $record->username); $this->errorCode=false; } return !$this->errorCode; } public function getId() { return $this->_id; } }
到如今已经准备的差很少了,简单画了一下登陆的流程.以下:
写到这里,就完成了基本的登陆流程.当有用户来访问的时候咱们就能够实现必须强制登陆.其实我上面所说的东西,在官方的文档上也有不少描述,能够多啃啃手册.
上次我作了一个类比,把YII比做一个汽车工厂.此次.咱们能够把后台这个模块比做一个大的生产车间.那么咱们在main里面声明的AdminUsers类的实例就至关于一个管理这个生产车间的管理员,负责监管人员进入生产车间和离开生产车间,而AdminUserIdentity 这个基于用户名密码的验证类就至关于一个基于用户名密码的开门器.若是你没有相应的用户名密码.也不可以进入车间进行工做.
就写到这里.接下来要实现后台用户的管理.增删改查功能.若是你耐心的看完了这篇博文并以为有收货的话,请帮忙赞一下.