- 浏览: 12327 次
- 性别:
- 来自: 北京
文章分类
最新评论
因为最近在做一个项目涉及到前后台登录问题,我是把后台作为一个模块(Module)来处理的。我看很多人放两个入口文件index.php和admin.php,然后分别指向前台和后台。这种方法固然很好,可以将前后台完全分离,但我总觉得这种方式有点牵强,这和两个应用啥区别?还不如做两个App用一个framework更好。而且Yii官方后台使用方法也是使用Module的方式。但是Moudle的方式有一个很头疼的问题,就是在使用Cwebuser登录时会出现前后台一起登录一起退出的问题,这显然是不合理的。我纠结了很久才找到下文即将介绍的方法,当然,很多也是参考别人的,自己稍作了改动。我一开始的做法是在后台登录时设置一个isadmin的session,然后再前台登录时注销这个session,这样做只能辨别是前台登录还是后台登录,但做不到前后台一起登录,也即前台登录了后台就退出了,后台登录了前台就退出了。出现这种原因的根本原因是我们使用了同一个Cwebuser实例,不能同时设置前后台session,要解决这个问题就要将前后台使用不同的Cwebuser实例登录。下面是我的做法,首先看protected->config->main.php里对前台user(Cwebuser)的配置:
'user'=>array(
'class'=>'WebUser',//这个WebUser是继承CwebUser,稍后给出它的代码
'stateKeyPrefix'=>'member',//这个是设置前台session的前缀
'allowAutoLogin'=>true,//这里设置允许cookie保存登录信息,一边下次自动登录
),
在你用Gii生成一个admin(即后台模块名称)模块时,会在module->admin下生成一个AdminModule.php文件,该类继承了CWebModule类,下面给出这个文件的代码,关键之处就在该文件,望大家仔细研究:
<?php
class AdminModule extends CWebModule
{
public function init()
{
// this method is called when the module is being created
// you may place code here to customize the module or the application
parent::init();//这步是调用main.php里的配置文件
// import the module-level models and componen
$this->setImport(array(
'admin.models.*',
'admin.components.*',
));
//这里重写父类里的组件
//如有需要还可以参考API添加相应组件
Yii::app()->setComponents(array(
'errorHandler'=>array(
'class'=>'CErrorHandler',
'errorAction'=>'admin/default/error',
),
'admin'=>array(
'class'=>'AdminWebUser',//后台登录类实例
'stateKeyPrefix'=>'admin',//后台session前缀
'loginUrl'=>Yii::app()->createUrl('admin/default/login'),
),
), false);
//下面这两行我一直没搞定啥意思,貌似CWebModule里也没generatorPaths属性和findGenerators()方法
//$this->generatorPaths[]='admin.generators';
//$this->controllerMap=$this->findGenerators();
}
public function beforeControllerAction($controller, $action)
{
if(parent::beforeControllerAction($controller, $action))
{
$route=$controller->id.'/'.$action->id;
if(!$this->allowIp(Yii::app()->request->userHostAddress) && $route!=='default/error')
throw new CHttpException(403,"You are not allowed to access this page.");
$publicPages=array(
'default/login',
'default/error',
);
if(Yii::app()->admin->isGuest && !in_array($route,$publicPages))
Yii::app()->admin->loginRequired();
else
return true;
}
return false;
}
protected function allowIp($ip)
{
if(empty($this->ipFilters))
return true;
foreach($this->ipFilters as $filter)
{
if($filter==='*' || $filter===$ip || (($pos=strpos($filter,'*'))!==false && !strncmp($ip,$filter,$pos)))
return true;
}
return false;
}
}
?>
AdminModule 的init()方法就是给后台配置另外的登录实例,让前后台使用不同的CWebUser,并设置后台session前缀,以便与前台session区别开来(他们同事存在$_SESSION这个数组里,你可以打印出来看看)。
这样就已经做到了前后台登录分离开了,但是此时你退出的话你就会发现前后台一起退出了。于是我找到了logout()这个方法,发现他有一个参数$destroySession=true,原来如此,如果你只是logout()的话那就会将session全部注销,加一个false参数的话就只会注销当前登录实例的session了,这也就是为什么要设置前后台session前缀的原因了,下面我们看看设置了false参数的logout方法是如何注销session的:
/**
* Clears all user identity information from persistent storage.
* This will remove the data stored via {@link setState}.
*/
public function clearStates()
{
$keys=array_keys($_SESSION);
$prefix=$this->getStateKeyPrefix();
$n=strlen($prefix);
foreach($keys as $key)
{
if(!strncmp($key,$prefix,$n))
unset($_SESSION[$key]);
}
}
看到没,就是利用匹配前缀的去注销的。
到此,我们就可以做到前后台登录分离,退出分离了。这样才更像一个应用,是吧?嘿嘿…
差点忘了说明一下:
Yii::app()->user //前台访问用户信息方法
Yii::app()->admin //后台访问用户信息方法
不懂的仔细看一下刚才前后台CWebUser的配置。
附件1:WebUser.php代码:
<?php
class WebUser extends CWebUser
{
public function __get($name)
{
if ($this->hasState('__userInfo')) {
$user=$this->getState('__userInfo',array());
if (isset($user[$name])) {
return $user[$name];
}
}
return parent::__get($name);
}
public function login($identity, $duration) {
$this->setState('__userInfo', $identity->getUser());
parent::login($identity, $duration);
}
}
?>
附件2:AdminWebUser.php代码
<?php
class AdminWebUser extends CWebUser
{
public function __get($name)
{
if ($this->hasState('__adminInfo')) {
$user=$this->getState('__adminInfo',array());
if (isset($user[$name])) {
return $user[$name];
}
}
return parent::__get($name);
}
public function login($identity, $duration) {
$this->setState('__adminInfo', $identity->getUser());
parent::login($identity, $duration);
}
}
?>
附件三:前台UserIdentity.php代码
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/
public $user;
public $_id;
public $username;
public function authenticate()
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
$user=User::model()->find('username=:username',array(':username'=>$this->username));
if ($user)
{
$encrypted_passwd=trim($user->password);
$inputpassword = trim(md5($this->password));
if($inputpassword===$encrypted_passwd)
{
$this->errorCode=self::ERROR_NONE;
$this->setUser($user);
$this->_id=$user->id;
$this->username=$user->username;
//if(isset(Yii::app()->user->thisisadmin))
// unset (Yii::app()->user->thisisadmin);
}
else
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
}
}
else
{
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
unset($user);
return !$this->errorCode;
}
public function getUser()
{
return $this->user;
}
public function getId()
{
return $this->_id;
}
public function getUserName()
{
return $this->username;
}
public function setUser(CActiveRecord $user)
{
$this->user=$user->attributes;
}
}
附件四:后台UserIdentity.php代码
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/
public $admin;
public $_id;
public $username;
public function authenticate()
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
$user=Staff::model()->find('username=:username',array(':username'=>$this->username));
if ($user)
{
$encrypted_passwd=trim($user->password);
$inputpassword = trim(md5($this->password));
if($inputpassword===$encrypted_passwd)
{
$this->errorCode=self::ERROR_NONE;
$this->setUser($user);
$this->_id=$user->id;
$this->username=$user->username;
// Yii::app()->user->setState("thisisadmin", "true");
}
else
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
}
}
else
{
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
unset($user);
return !$this->errorCode;
}
public function getUser()
{
return $this->admin;
}
public function getId()
{
return $this->_id;
}
public function getUserName()
{
return $this->username;
}
public function setUser(CActiveRecord $user)
{
$this->admin=$user->attributes;
}
}
'user'=>array(
'class'=>'WebUser',//这个WebUser是继承CwebUser,稍后给出它的代码
'stateKeyPrefix'=>'member',//这个是设置前台session的前缀
'allowAutoLogin'=>true,//这里设置允许cookie保存登录信息,一边下次自动登录
),
在你用Gii生成一个admin(即后台模块名称)模块时,会在module->admin下生成一个AdminModule.php文件,该类继承了CWebModule类,下面给出这个文件的代码,关键之处就在该文件,望大家仔细研究:
<?php
class AdminModule extends CWebModule
{
public function init()
{
// this method is called when the module is being created
// you may place code here to customize the module or the application
parent::init();//这步是调用main.php里的配置文件
// import the module-level models and componen
$this->setImport(array(
'admin.models.*',
'admin.components.*',
));
//这里重写父类里的组件
//如有需要还可以参考API添加相应组件
Yii::app()->setComponents(array(
'errorHandler'=>array(
'class'=>'CErrorHandler',
'errorAction'=>'admin/default/error',
),
'admin'=>array(
'class'=>'AdminWebUser',//后台登录类实例
'stateKeyPrefix'=>'admin',//后台session前缀
'loginUrl'=>Yii::app()->createUrl('admin/default/login'),
),
), false);
//下面这两行我一直没搞定啥意思,貌似CWebModule里也没generatorPaths属性和findGenerators()方法
//$this->generatorPaths[]='admin.generators';
//$this->controllerMap=$this->findGenerators();
}
public function beforeControllerAction($controller, $action)
{
if(parent::beforeControllerAction($controller, $action))
{
$route=$controller->id.'/'.$action->id;
if(!$this->allowIp(Yii::app()->request->userHostAddress) && $route!=='default/error')
throw new CHttpException(403,"You are not allowed to access this page.");
$publicPages=array(
'default/login',
'default/error',
);
if(Yii::app()->admin->isGuest && !in_array($route,$publicPages))
Yii::app()->admin->loginRequired();
else
return true;
}
return false;
}
protected function allowIp($ip)
{
if(empty($this->ipFilters))
return true;
foreach($this->ipFilters as $filter)
{
if($filter==='*' || $filter===$ip || (($pos=strpos($filter,'*'))!==false && !strncmp($ip,$filter,$pos)))
return true;
}
return false;
}
}
?>
AdminModule 的init()方法就是给后台配置另外的登录实例,让前后台使用不同的CWebUser,并设置后台session前缀,以便与前台session区别开来(他们同事存在$_SESSION这个数组里,你可以打印出来看看)。
这样就已经做到了前后台登录分离开了,但是此时你退出的话你就会发现前后台一起退出了。于是我找到了logout()这个方法,发现他有一个参数$destroySession=true,原来如此,如果你只是logout()的话那就会将session全部注销,加一个false参数的话就只会注销当前登录实例的session了,这也就是为什么要设置前后台session前缀的原因了,下面我们看看设置了false参数的logout方法是如何注销session的:
/**
* Clears all user identity information from persistent storage.
* This will remove the data stored via {@link setState}.
*/
public function clearStates()
{
$keys=array_keys($_SESSION);
$prefix=$this->getStateKeyPrefix();
$n=strlen($prefix);
foreach($keys as $key)
{
if(!strncmp($key,$prefix,$n))
unset($_SESSION[$key]);
}
}
看到没,就是利用匹配前缀的去注销的。
到此,我们就可以做到前后台登录分离,退出分离了。这样才更像一个应用,是吧?嘿嘿…
差点忘了说明一下:
Yii::app()->user //前台访问用户信息方法
Yii::app()->admin //后台访问用户信息方法
不懂的仔细看一下刚才前后台CWebUser的配置。
附件1:WebUser.php代码:
<?php
class WebUser extends CWebUser
{
public function __get($name)
{
if ($this->hasState('__userInfo')) {
$user=$this->getState('__userInfo',array());
if (isset($user[$name])) {
return $user[$name];
}
}
return parent::__get($name);
}
public function login($identity, $duration) {
$this->setState('__userInfo', $identity->getUser());
parent::login($identity, $duration);
}
}
?>
附件2:AdminWebUser.php代码
<?php
class AdminWebUser extends CWebUser
{
public function __get($name)
{
if ($this->hasState('__adminInfo')) {
$user=$this->getState('__adminInfo',array());
if (isset($user[$name])) {
return $user[$name];
}
}
return parent::__get($name);
}
public function login($identity, $duration) {
$this->setState('__adminInfo', $identity->getUser());
parent::login($identity, $duration);
}
}
?>
附件三:前台UserIdentity.php代码
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/
public $user;
public $_id;
public $username;
public function authenticate()
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
$user=User::model()->find('username=:username',array(':username'=>$this->username));
if ($user)
{
$encrypted_passwd=trim($user->password);
$inputpassword = trim(md5($this->password));
if($inputpassword===$encrypted_passwd)
{
$this->errorCode=self::ERROR_NONE;
$this->setUser($user);
$this->_id=$user->id;
$this->username=$user->username;
//if(isset(Yii::app()->user->thisisadmin))
// unset (Yii::app()->user->thisisadmin);
}
else
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
}
}
else
{
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
unset($user);
return !$this->errorCode;
}
public function getUser()
{
return $this->user;
}
public function getId()
{
return $this->_id;
}
public function getUserName()
{
return $this->username;
}
public function setUser(CActiveRecord $user)
{
$this->user=$user->attributes;
}
}
附件四:后台UserIdentity.php代码
<?php
/**
* UserIdentity represents the data needed to identity a user.
* It contains the authentication method that checks if the provided
* data can identity the user.
*/
class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/
public $admin;
public $_id;
public $username;
public function authenticate()
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
$user=Staff::model()->find('username=:username',array(':username'=>$this->username));
if ($user)
{
$encrypted_passwd=trim($user->password);
$inputpassword = trim(md5($this->password));
if($inputpassword===$encrypted_passwd)
{
$this->errorCode=self::ERROR_NONE;
$this->setUser($user);
$this->_id=$user->id;
$this->username=$user->username;
// Yii::app()->user->setState("thisisadmin", "true");
}
else
{
$this->errorCode=self::ERROR_PASSWORD_INVALID;
}
}
else
{
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
unset($user);
return !$this->errorCode;
}
public function getUser()
{
return $this->admin;
}
public function getId()
{
return $this->_id;
}
public function getUserName()
{
return $this->username;
}
public function setUser(CActiveRecord $user)
{
$this->admin=$user->attributes;
}
}
发表评论
-
Yii学习 第八章:迭代5:用户访问控制
2015-12-28 23:15 506迭代计划 针对一个Project我们建立了如下的三类角色模型 ... -
PHP获取图片宽度高度、大小尺寸、图片类型、用于布局的img属性
2015-12-28 14:16 792//php自带函数 getimagesize() $img_i ... -
Yii框架中setFlash和getFlash函数的用法
2015-12-21 17:49 775设置键值名为success的临时信息,在getFlash后删除 ... -
yii 常用一些调用 (增加中)
2015-12-21 17:47 781调用YII框架中 jquery:Yii::app()-> ... -
Yii获取当前url和域名的方法
2015-12-11 16:35 1022本文实例讲述了Yii获取当前url和域名的方法 。具体如下: ... -
PHP的file_put_content函数用法
2015-12-09 22:06 803file_put_content("d:/mylog ... -
支付宝支付与微信支付服务端回调notify_url数据的区别
2015-12-09 21:37 1615支付宝和微信的回调地址 notifyUrl = Reques ...
相关推荐
主要介绍了Yii中实现处理前后台登录的新方法,具体分析了Yii中前后台登录的新思路与相关实现技巧,需要的朋友可以参考下
yii简易后台基础模板
yii 2.0通用后台系统管理,实现注册登录上传用户自定义头像
带权限管理的yii2.0后台框架,适合任何情况,最新的值得使用
NULL 博文链接:https://hudeyong926.iteye.com/blog/1396657
yii1.1中文文档 yii框架中文手册教程.pdf
Yii是一个全栈式的MVC框架,所谓全栈式指的是Yii框架本身实现了web开发中所要用到的所有功能,比如MVC,ORM(DAO/ActiveRecord), 全球化(I18N/L10N), 缓存(caching), 基于jQuery Ajax支持(jQuery-based AJAX support), ...
Yii2参考手册,Yii2中文手册完整版
Yii 2.0 权威指南 本教程的发布遵循 Yii 文档使用许可. 版权所有 2014 (c) Yii Software LLC. 介绍 已定稿 关于 Yii 已定稿 从 Yii 1.1 升级 入门 已定稿 安装 Yii 已定稿 运行应用 已定稿 第一次问候 已定稿 ...
yii2后台,可用于网站后台界面的建设,简介,明了的界面!!!
系统基于yii2高级版本开发,后台模板使用的 Ace Admin。对于一般的后台开发,比较方便; 对于数据表的CURL操作都有封装,且所有操作都有权限控制。现在这个项目只是一个示例项目, 主要功能被我移到: [jinxing/yii2-...
它将 Web 编程中的可重用性发挥到极致,能够显著加速开发进程。Yii(读作“易”)代表简单(easy)、高效(efficient)、可扩展(extensible)。 需求 要运行一个基于 Yii 开发的 Web 应用,你需要一个支持 PHP 5.1.0 ...
YII框架中文手册,希望帮助需要帮助的人!
yii 最新版
Yii2.0中文学习手册
主要介绍了Yii2 中实现单点登录的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架很好用yii框架
权威的yii框架中文版开发文档,希望能够为您的yii框架学习带来帮助,让你的技术更上一层楼! zhihuizhan.com
yii框架中文手册教程和YII模板 我很辛苦才找到的