Yii中实现处理前后台登录的新方法


Posted in PHP onDecember 28, 2015

本文实例讲述了Yii中实现处理前后台登录的新方法。分享给大家供大家参考,具体如下:

因为最近在做一个项目涉及到前后台登录问题,我是把后台作为一个模块(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);
  }
}
?>

附件3:前台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;
  }
}

附件4:后台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框架的PHP程序设计有所帮助。

PHP 相关文章推荐
从php核心代码分析require和include的区别
Jan 02 PHP
PHP stream_context_create()作用和用法分析
Mar 29 PHP
php判断上传的Excel文件中是否有图片及PHPExcel库认识
Jan 11 PHP
php中is_null,empty,isset,unset 的区别详细介绍
Apr 28 PHP
对PHP语言认识上需要避免的10大误区
Jun 12 PHP
PHP中使用Memache作为进程锁的操作类分享
Mar 30 PHP
php身份证号码检查类实例
Jun 18 PHP
[原创]php简单隔行变色功能实现代码
Jul 09 PHP
PHP中的密码加密的解决方案总结
Oct 26 PHP
浅谈php中的访问修饰符private、protected、public的作用范围
Nov 20 PHP
PHP命名空间namespace及use的简单用法分析
Aug 03 PHP
对laravel的csrf 防御机制详解,及form中csrf_token()的存在介绍
Oct 24 PHP
Yii中CGridView实现批量删除的方法
Dec 28 #PHP
Yii基于数组和对象的Model查询技巧实例详解
Dec 28 #PHP
yii权限控制的方法(三种方法)
Dec 28 #PHP
Yii使用Captcha验证码的方法
Dec 28 #PHP
yii使用activeFileField控件实现上传文件与图片的方法
Dec 28 #PHP
yii实现使用CUploadedFile上传文件的方法
Dec 28 #PHP
Yii中Model(模型)的创建及使用方法
Dec 28 #PHP
You might like
人脸识别测颜值、测脸龄、测相似度微信接口
2016/04/07 PHP
PHP实现的统计数据功能详解
2016/12/06 PHP
Laravel修改验证提示信息为中文的示例
2019/10/23 PHP
jQuery ui1.7 dialog只能弹出一次问题
2009/08/27 Javascript
基于jQuery的日期选择控件
2009/10/27 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
中国地区三级联动下拉菜单效果分析
2012/11/15 Javascript
Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法
2014/09/01 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
ajax跨域调用webservice的实现代码
2016/05/09 Javascript
jquery mobile 实现自定义confirm确认框效果的简单实例
2016/06/17 Javascript
JavaScript中Promise的使用详解
2017/02/26 Javascript
微信小程序 参数传递实例代码
2017/03/20 Javascript
解决vue2.x中数据渲染以及vuex缓存的问题
2017/07/13 Javascript
利用ES6的Promise.all实现至少请求多长时间的实例
2017/08/28 Javascript
解决微信小程序scroll-view组件无横向滚动的问题
2020/02/04 Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
2020/02/11 Javascript
vue+vant使用图片预览功能ImagePreview的问题解决
2020/04/10 Javascript
关于JavaScript数组去重的一些理解汇总
2020/09/10 Javascript
python实现给数组按片赋值的方法
2015/07/28 Python
Python使用matplotlib绘制Logistic曲线操作示例
2019/11/28 Python
Python装饰器原理与基本用法分析
2020/01/07 Python
python实现文字版扫雷
2020/04/24 Python
使用tensorflow框架在Colab上跑通猫狗识别代码
2020/04/26 Python
python+selenium 简易地疫情信息自动打卡签到功能的实现代码
2020/08/22 Python
html5需遵循的6个设计原则
2016/04/27 HTML / CSS
HTML5逐步分析实现拖放功能的方法
2020/09/30 HTML / CSS
BannerBuzz加拿大:在线定制横幅印刷、广告和标志
2020/03/10 全球购物
怎样有效的进行自我评价
2013/10/06 职场文书
乡镇庆八一活动方案
2014/02/02 职场文书
九华山导游词
2015/02/03 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书
银行安全保卫工作总结
2015/08/10 职场文书
该怎么书写道歉信?
2019/07/03 职场文书
小学生六年级作文之关于感恩
2019/08/16 职场文书
大学生党员暑假实践(活动总结)
2019/08/21 职场文书