飞嗨,欢迎您的光临,本博所发布之文章皆为作者亲测通过,如有错误,欢迎通过各种方式指正。(本博已于2015.12.6升级到php7,运行环境php7 php-fpm + nginx1.8.0)

yii2登陆过程追踪

PHP lf 2725℃ 0评论

yii2框架把yii\web\User作为内置核心组件,应用启动过程中,自动加载。在做sso登录的过程中,需要重写覆盖yii\web\User中的一些方法,所以梳理了一下yii2 user组件。yii2登录由必需实现自yii\web\IdentityInterface接口的identityClass和yii\web\User实现。

passport

        

        接触yii2框架有很长一段时间了,之前项目一直想使用yii2,但是苦于没有发现基于yii2的比较完善漂亮的后台,所以呢,前段时间,花了半年多时间,利用业余时间自己写了一个基于yii2的cms系统,还是beta版中,但是基本的功能都已经有了,自我感觉比一般的后台还是漂亮哒。github地址: https://www.github.com/liufee/cms 欢迎试用并提交您的代码。

        最近这几周呢,不知啥心血来潮了,把刚大学毕业时写的老代码(大部分基于thinkphp)都改造一下,让他适应yii2框架,还别说,刚毕业那会虽然代码很渣,但是量还是挺大的!改造了几个业余项目的代码,发现很多项目中都有自己的注册登陆,为了站群之间用户的统一,决定用单点登录sso改造一下,于是乎,独立出一个passport的二级域名,用来做账户认证系统!在做的过程中,因为是基于yii2框架,遇到了不少困难,于是不得不研读了一下yii2登陆过程的component代码,然后才解决了单点登陆!下面有理解错误的地方,欢迎各位留言/QQ/email批评指正

        使用过yii2的都知道,yii2是基于组件的,登陆也不例外,作为yii2内置的一个核心组件,在yii\web\Application::coreComponents()自动加载了,所以在全局可以使用yii::$app->user来获取这个组件(单例模式)。

        yii2 user组件默认使用的类是yii\web\User,当然我们可以在config的component段中指定user组件使用自己的登陆认证过程类。user组件要求我们必须提供一个identityClass实现yii\web\IdentityInterface接口的findIdentity, findIdentity, findIdentityByAccessToken, getId, getAuthKey, ValidateAuthKey方法,这些东东就是在对比用户的账号密码。在登陆后,使用yii::$app->getUser90->getIdentity()得到的对象就是这个identityClass,在yii2 advanced模板中,这里默认配的就是commom\models\User。

'user' => [
     'class'=>'yii\web\User',
     'identityClass' => 'common\models\User',
      'enableAutoLogin' => true,
],

        在应用被访问的时候,加载user组件的时候,\yii\web\User::init()被自动执行,这里基本啥也没做,执行一下yii\base\Component的构造方法,因为这个组建用到了事件吗,然后判断一下user组件是否设置了identityClass,这个必须要设置,不设置就报错了。然后检查一下,如果开启了自动登陆,还要检查一下是不是设置了cookie名。

        如果我们的应用中,没有需要判断登陆的地方,那么这个组件几乎就没什么用了,但当我们尝试使用yii::$app->getUser()->getIsGuest()的时候,就会触发这里面的登陆过程了。在getIsGuest()方法中调用了getIdentity()方法,如果getIdentity()方法返回null那就是未登录了,且看getIdentity()方法,首先判断identity是否存在,比如在执行yii::$app->getUser()->getIsGuest()前执行了login代码yii::$app->getUser()->login(IdentityInterface $identity, $duration)那这里就返回identity了。否则,如果开启了自动登陆,就执行renewAuthStatus()方法。

        renewAuthStatus()方法中,先尝试使用session登陆,$id=$session->get($this->_idParam),调用identityClass::findIdentity($id),根据用户id找到用户的信息,找到了就设置identiy,未找到就设置identiy为null(用户登陆后被删除的情况).然后判断一下登陆时间是否过期,过期就调用logout()自动退出登陆了。当session登陆尝试完后,如果开启了自动登陆,还会尝试一下cookie登陆,如果刚才session登陆成功后执行renewIdentityCookie()方法,否则执行loginByCookie()尝试使用cookie登陆.


        loginByCookie(),首先调用getIdentityAndDurationFromCookie()方法,这里面主要是获取cookie,没有登陆cookie就返回null,反之解析cookie数据,根据cookie中的用户id调用IdentityClass::findIdentity($id),若这里的id找不到用户就调用removeIdentityCookie()删除登陆cookie,反之返回identity。接着触发登陆前事件,再调用switchIdentity()方法.


        switchIdentity()方法中,调用setIdentity()方法,这里就已经是登陆状态了。(switchIdentity方法接收两个参数,identity为null就是注销登陆了,不为空就是设置登陆了).然后就是一些善后工作了,如果开启了自动登陆,把旧的identity cookie都删除。删除登陆的session。并重新设置一个session用于登陆,这个session就是保存了用户的id。紧接着设置新的identity cookie,即调用sendIdentityCookie().


        sendIdentityCookie()方法,没啥,就是把用户id, authkey, duration序列化然后写进cookie.接着就又回到了loginByCookie()方法中,触发登陆后事件.至此,登陆完成.

        当然还有一种情况是,登陆页面点击登陆,那就是比对数据库的用户名密码,如果正确的话就调用yii::$app->getUser()->login($identity, $duration),就是设置一下user组件的identity就登陆成功了!

转载请注明:飞嗨 » yii2登陆过程追踪

喜欢 (11)or分享 (0)
发表我的评论
取消评论
表情
(14)个小伙伴在吐槽
  1. xss的测试shi sha
    匿名2018-11-02 16:46 回复
    • 就你皮
      lf2018-12-03 13:05 回复
  2. alert(11111111111111111111)
    匿名2018-07-02 15:15 回复
  3. 111111111111
    匿名2018-07-02 15:14 回复
  4. 发个评论试试看
    匿名2018-06-09 18:37 回复
  5. alert('1111')
    匿名2018-03-14 15:07 回复
    • 感谢对于本站xss的测试
      lf2018-03-28 09:30 回复
      • 哈哈哈
        匿名2018-03-30 10:47 回复
  6. :razz:
    匿名2018-03-14 15:06 回复
  7. :twisted:
    匿名2018-01-23 13:15 回复
  8. 没什么好说的,提前祝博主新年快乐!
    挖宝网2016-12-26 10:54 回复
  9. 掐指一算,这个博客能风光一百年!
    衣皇后2016-12-24 10:14 回复
粤ICP备15018643号-1