自动登录的原理很简单。主要就是利用cookie来实现的
在第一次登录的时候,如果登录成功并且选中了下次自动登录,那么就会把用户的认证信息保存到cookie中,cookie的有效期为1年或者几个月。

在下次登录的时候先判断cookie中是否存储了用户的信息,如果有则用cookie中存储的用户信息来登录,

配置User组件

首先在配置文件的components中设置user组件

'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],

我们看到enableAutoLogin就是用来判断是否要启用自动登录功能,这个和界面上的下次自动登录无关。
只有在enableAutoLogin为true的情况下,如果选择了下次自动登录,那么就会把用户信息存储起来放到cookie中并设置cookie的有效期为3600*24*30秒,以用于下次登录

现在我们来看看Yii中是怎样实现的。

一、第一次登录存cookie

1、login 登录功能

public function login($identity, $duration = 0)
    {
        if ($this->beforeLogin($identity, false, $duration)) {
            $this->switchIdentity($identity, $duration);
            $id = $identity->getId();
            $ip = Yii::$app->getRequest()->getUserIP();
            Yii::info("User '$id' logged in from $ip with duration $duration.", __METHOD__);
            $this->afterLogin($identity, false, $duration);
        }

return !$this->getIsGuest();
    }

在这里,就是简单的登录,然后执行switchIdentity方法,设置认证信息。

2、switchIdentity设置认证信息

public function switchIdentity($identity, $duration = 0)
    {
        $session = Yii::$app->getSession();
        if (!YII_ENV_TEST) {
            $session->regenerateID(true);
        }
        $this->setIdentity($identity);
        $session->remove($this->idParam);
        $session->remove($this->authTimeoutParam);
        if ($identity instanceof IdentityInterface) {
            $session->set($this->idParam, $identity->getId());
            if ($this->authTimeout !== null) {
                $session->set($this->authTimeoutParam, time() + $this->authTimeout);
            }
            if ($duration > 0 && $this->enableAutoLogin) {
                $this->sendIdentityCookie($identity, $duration);
            }
        } elseif ($this->enableAutoLogin) {
            Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
        }
    }

这个方法比较重要,在退出的时候也需要调用这个方法。

这个方法主要有三个功能

  • 设置session的有效期
  • 如果cookie的有效期大于0并且允许自动登录,那么就把用户的认证信息保存到cookie中
  • 如果允许自动登录,删除cookie信息。这个是用于退出的时候调用的。退出的时候传递进来的$identity为null

protected function sendIdentityCookie($identity, $duration)
    {
        $cookie = new Cookie($this->identityCookie);
        $cookie->value = json_encode([
            $identity->getId(),
            $identity->getAuthKey(),
            $duration,
        ]);
        $cookie->expire = time() + $duration;
        Yii::$app->getResponse()->getCookies()->add($cookie);
    }

存储在cookie中的用户信息包含有三个值:

  • $identity->getId()
  • $identity->getAuthKey()
  • $duration

getId()和getAuthKey()是在IdentityInterface接口中的。我们也知道在设置User组件的时候,这个User Model是必须要实现IdentityInterface接口的。所以,可以在User Model中得到前两个值,第三值就是cookie的有效期。

二、自动从cookie登录

从上面我们知道用户的认证信息已经存储到cookie中了,那么下次的时候直接从cookie里面取信息然后设置就可以了。

1、AccessControl用户访问控制

Yii提供了AccessControl来判断用户是否登录,有了这个就不需要在每一个action里面再判断了

public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['logout'],
                'rules' => [
                    [
                        'actions' => ['logout'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
        ];
    }

2、getIsGuest、getIdentity判断是否认证用户

isGuest是自动登录过程中最重要的属性。
在上面的AccessControl访问控制里面通过IsGuest属性来判断是否是认证用户,然后在getIsGuest方法里面是调用getIdentity来获取用户信息,如果不为空就说明是认证用户,否则就是游客(未登录)。

public function getIsGuest($checkSession = true)
    {
        return $this->getIdentity($checkSession) === null;
    }
    public function getIdentity($checkSession = true)
    {
        if ($this->_identity === false) {
            if ($checkSession) {
                $this->renewAuthStatus();
            } else {
                return null;
            }
        }

return $this->_identity;
    }

3、renewAuthStatus 重新生成用户认证信息

protected function renewAuthStatus()
    {
        $session = Yii::$app->getSession();
        $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null;

if ($id === null) {
            $identity = null;
        } else {
            /** @var IdentityInterface $class */
            $class = $this->identityClass;
            $identity = $class::findIdentity($id);
        }

$this->setIdentity($identity);

if ($this->authTimeout !== null && $identity !== null) {
            $expire = $session->get($this->authTimeoutParam);
            if ($expire !== null && $expire < time()) {
                $this->logout(false);
            } else {
                $session->set($this->authTimeoutParam, time() + $this->authTimeout);
            }
        }

if ($this->enableAutoLogin) {
            if ($this->getIsGuest()) {
                $this->loginByCookie();
            } elseif ($this->autoRenewCookie) {
                $this->renewIdentityCookie();
            }
        }
    }
这一部分先通过session来判断用户,因为用户登录后就已经存在于session中了。然后再判断如果是自动登录,那么就通过cookie信息来登录。

4、通过保存的Cookie信息来登录 loginByCookie

protected function loginByCookie()
    {
        $name = $this->identityCookie['name'];
        $value = Yii::$app->getRequest()->getCookies()->getValue($name);
        if ($value !== null) {
            $data = json_decode($value, true);
            if (count($data) === 3 && isset($data[0], $data[1], $data[2])) {
                list ($id, $authKey, $duration) = $data;
                /** @var IdentityInterface $class */
                $class = $this->identityClass;
                $identity = $class::findIdentity($id);
                if ($identity !== null && $identity->validateAuthKey($authKey)) {
                    if ($this->beforeLogin($identity, true, $duration)) {
                        $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
                        $ip = Yii::$app->getRequest()->getUserIP();
                        Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__);
                        $this->afterLogin($identity, true, $duration);
                    }
                } elseif ($identity !== null) {
                    Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
                }
            }
        }
    }

先读取cookie值,然后$data = json_decode($value, true);反序列化为数组。

这个从上面的代码可以知道要想实现自动登录,这三个值都必须有值。另外,在User Model中还必须要实现findIdentity、validateAuthKey这两个方法。

登录完成后,还可以再重新设置cookie的有效期,这样便能一起有效下去了。

$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);

三、退出 logout

public function logout($destroySession = true)
    {
        $identity = $this->getIdentity();
        if ($identity !== null && $this->beforeLogout($identity)) {
            $this->switchIdentity(null);
            $id = $identity->getId();
            $ip = Yii::$app->getRequest()->getUserIP();
            Yii::info("User '$id' logged out from $ip.", __METHOD__);
            if ($destroySession) {
                Yii::$app->getSession()->destroy();
            }
            $this->afterLogout($identity);
        }

return $this->getIsGuest();
    }

public function switchIdentity($identity, $duration = 0)
    {
        $session = Yii::$app->getSession();
        if (!YII_ENV_TEST) {
            $session->regenerateID(true);
        }
        $this->setIdentity($identity);
        $session->remove($this->idParam);
        $session->remove($this->authTimeoutParam);
        if ($identity instanceof IdentityInterface) {
            $session->set($this->idParam, $identity->getId());
            if ($this->authTimeout !== null) {
                $session->set($this->authTimeoutParam, time() + $this->authTimeout);
            }
            if ($duration > 0 && $this->enableAutoLogin) {
                $this->sendIdentityCookie($identity, $duration);
            }
        } elseif ($this->enableAutoLogin) {
            Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie));
        }
    }

退出的时候先把当前的认证设置为null,然后再判断如果是自动登录功能则再删除相关的cookie信息。

yii2 登录、退出、自动登录的更多相关文章

  1. spring boot:spring security给用户登录增加自动登录及图形验证码功能(spring boot 2.3.1)

    一,图形验证码的用途? 1,什么是图形验证码? 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers ...

  2. cookie理解与实践【实现简单登录以及自动登录功能】

    cookie理解 Cookie是由W3C组织提出,最早由netscape社区发展的一种机制 http是无状态协议.当某次连接中数据提交完,连接会关闭,再次访问时,浏览器与服务器需要重新建立新的连接: ...

  3. andorid 应用第二次登录实现自动登录

    前置条件是所有用户相关接口都走 https,非用户相关列表类数据走 http. 步骤 第一次登陆 getUserInfo 里带有一个长效 token,该长效 token 用来判断用户是否登陆和换取短 ...

  4. 移动端APP第一次登录和自动登录流程

    App登陆保存数据流程App因为要实现自动登陆功能,所以必然要保存一些凭据,所以比较复杂. App登陆要实现的功能: 密码不会明文存储,并且不能反编绎解密: 在服务器端可以控制App端的登陆有效性,防 ...

  5. springboot+layui实现PC端用户的增删改查 & 整合mui实现app端的自动登录和用户的上拉加载 & HBuilder打包app并在手机端下载安装

    springboot整合web开发的各个组件在前面已经有详细的介绍,下面是用springboot整合layui实现了基本的增删改查. 同时在学习mui开发app,也就用mui实现了一个简单的自动登录和 ...

  6. delphi如何在form显示出来后处理指定的事件(例如自动登录)

    最近写一个delphi客户端,遇到一个自动登录问题,已经解决了思路如下: 1.在Form的oncreate事件中读取用户配置文件,检查及处理是否保存了用户密码,是否自动登录,如果需要自动登录, 自动登 ...

  7. 基于Requests和BeautifulSoup实现“自动登录”

    基于Requests和BeautifulSoup实现“自动登录”实例 自动登录抽屉新热榜 #!/usr/bin/env python # -*- coding:utf-8 -*- import req ...

  8. PHP简单登录退出代码

    PHP简单登录退出代码 登录页面login.html 负责收集用户填写的登录信息.  <html> <head> <title></title> < ...

  9. python 奇淫技巧之自动登录 哔哩哔哩

    前言 嘿,各位小伙伴好呀,今天要带来点什么干货呢,就从我的实际开发中来给大家带来一个案例吧,如何自动登录 哔哩哔哩 接到老大通知,让我自动写一个自动登录 哔哩哔哩 的脚本,我当然是二话不说直接开怼,咱 ...

随机推荐

  1. 【转】wait,notify,notifyAll,join,yield,sleep的区别和联系

    1.  Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调 ...

  2. Android studio:从Eclipse迁移到Android Studio【一】

    转载:http://www.apkbus.com/forum.php?mod=viewthread&tid=255061&extra=page%3D2%26filter%3Dautho ...

  3. ng-学习笔记1

    1.ng-model绑定输入域的数据到控制器的属性.修改输入域的值,属性的值也将修改(双向绑定) 2.ng-repeat可用于创建表格,使用 <td>{{ $index + 1 }}< ...

  4. 【BZOJ-3438】小M的作物 最小割 + 最大权闭合图

    3438: 小M的作物 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 825  Solved: 368[Submit][Status][Discuss ...

  5. MySoft.Data 2.7.3版本的GitHub托管(ORM升级封装)

    MySoft.Data 2.7.3 dotnet ORM 版权 这里版权属于老毛:http://www.cnblogs.com/maoyong 说明 MySoft体系中的ORM组件,这里的版本为2.7 ...

  6. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  7. cookielib和urllib2模块相结合模拟网站登录

    1.cookielib模块 cookielib模块的主要作用是提供可存储cookie的对象,以便于与urllib2模块配合使用来访问Internet资源.例如可以利用 本模块的CookieJar类的对 ...

  8. dubbo 学习总结

    1 Dubbo 配置 dubbo配置xml配置     属性配置  注解配置   api配置 注解配置 (+) (#) 服务提供方注解: import com.alibaba.dubbo.config ...

  9. requst方法简单用一下

    使用getParametar() 获取表单提交过来的文本框的值 setAttribute(String name, Object o)存储此请求中的属性.在请求之间重置属性.此方法常常与 Reques ...

  10. 软件产品案例分析--K米

    软件产品案例分析--K米 第一部分 调研,评测 评测 个人第一次上手体验 使用的第一款点歌软件,以为就是个遥控而已,使用后发现功能还挺多,能点挺久.觉得很方便,不用挤成一堆点歌了.K米的脸蛋(UI)好 ...