数字派

数字派

我就是个数字派,我有无限的可能,但是我不会陷入循环。

  • 财富值1515
  • 威望值10
  • 总积分2135

个人信息

  • 提出了问题
    如果自己做rbac权限管理?
  • 2016-11-17 已签到
    连续签到4天,获得了20个金钱
  • 回复了 的回答

    我也遇到了同样的问题,不知道现在你解决了吗,能告诉我吗,困扰我好几天了...

    问题解决了么,我也遇到这个问题了

  • 收藏了教程
    Yii 2.0 RBAC 权限学习笔记
  • 2016-11-16 已签到
    连续签到3天,获得了15个金钱
  • 回复了 的回答

    先说自动登录,cookie在哪里设置的,允许自动登录必须得启用enableAutoLogin,设置为true

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

    然后看登录,在你的LoginFrom中的login方法有这么一行代码:

    return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    

    也是真正执行登录操作的代码,他实际上调用的是\yii\web\User的login方法,这个类的实际路径在:盘符/项目名/vendor/yiisoft/yii2/web/User.php

    public function login(IdentityInterface $identity, $duration = 0)
    {
    	if ($this->beforeLogin($identity, false, $duration)) {
    		$this->switchIdentity($identity, $duration);
                    ............
    		...其他代码..
    		...........
    	}
    	......
    }
    

    首先执行登录之前的操作,然后,关键是$this->switchIdentity($identity, $duration)这个方法:

    public function switchIdentity($identity, $duration = 0)
    {
    	......
        ......
    	if ($identity) {
    		......
    		......
    		if ($duration > 0 && $this->enableAutoLogin) {
    			$this->sendIdentityCookie($identity, $duration);
    		}
    	} elseif ($this->enableAutoLogin) {
    		......
    	}
    }
    

    在$this->sendIdentityCookie($identity, $duration);这里把cookie设置进去

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

    Yii::$app->getResponse()->getCookies()->add($cookie); 这里设置cookie

    到这里,应该解决了cookie的设置的问题了吧。

    然后说说自动登录的实现
    在SiteController中的actionLogin()方法,他判断这个用户是不是登录用户,如果不是,则返回主页或者说登录页

    if (!\Yii::$app->user->isGuest) {
                return $this->goHome();
    }
    

    还是走到\yii\web\User这个类,调用了getIsGuest()方法,getIsGuest()方法调用getIdentity($autoRenew = true)方法

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

    是否开启自动登录($this->enableSession && $autoRenew),是,那么执行renewAuthStatus()方法:

    protected function renewAuthStatus()
    {
    	......
    	...前面代码是session有值的判断,不看他...
    	......
    
    	if ($this->enableAutoLogin) {
    		if ($this->getIsGuest()) {
    			$this->loginByCookie();
    		} elseif ($this->autoRenewCookie) {
    			$this->renewIdentityCookie();
    		}
    	}
    }
    

    启用自动登录$this->enableAutoLogin为true,然后判断是否是访客$this->getIsGuest(),如果是,则执行登录,从cookie登录$this->loginByCookie();这就是cookie登录的具体实现

    protected function loginByCookie()
        {
    		//cookie取值
            $value = Yii::$app->getRequest()->getCookies()->getValue($this->identityCookie['name']);
            if ($value === null) {
                return;
            }
    
            $data = json_decode($value, true);
            if (count($data) !== 3 || !isset($data[0], $data[1], $data[2])) {
                return;
            }
    
            list ($id, $authKey, $duration) = $data;
            /* @var $class IdentityInterface */
            $class = $this->identityClass;
            $identity = $class::findIdentity($id);
            if ($identity === null) {
                return;
            } elseif (!$identity instanceof IdentityInterface) {
                throw new InvalidValueException("$class::findIdentity() must return an object implementing IdentityInterface.");
            }
    
            if ($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);
                }
            } else {
                Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
            }
        }
    

    $identity = $class::findIdentity($id);//根据cookie保存的记录id在数据库中找,这里调用的是在配置文件中main.php配置的

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

    common\models\User这个类的findIdentity($id)方法

    public static function findIdentity($id)
        {
            return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
        }
    

    if ($identity->validateAuthKey($authKey)) {} 则调用 common\models\User这个类的validateAuthKey($authKey)方法,实际上就是判断这个记录id的auth_key这个数据库的值是否跟保存到cookie中的一样,如果一样,返回true。
    目的是,所以,如果管理员要修改一个帐号的密码,实际上出了修改他的密码password_hash之外,还需要修改auth_key,否则他如果以前登录过。cookie有值,一样可以正常登录。这点很重要

    然后就没啥好说的拉,就是正常的登录流程拉,个人建议,好好利用ide的debug功能,跟踪代码绝对杠杠的

    cookie登录,用户每次进入页面都要if一次?

  • 回复了 的回答

    先说自动登录,cookie在哪里设置的,允许自动登录必须得启用enableAutoLogin,设置为true

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

    然后看登录,在你的LoginFrom中的login方法有这么一行代码:

    return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    

    也是真正执行登录操作的代码,他实际上调用的是\yii\web\User的login方法,这个类的实际路径在:盘符/项目名/vendor/yiisoft/yii2/web/User.php

    public function login(IdentityInterface $identity, $duration = 0)
    {
    	if ($this->beforeLogin($identity, false, $duration)) {
    		$this->switchIdentity($identity, $duration);
                    ............
    		...其他代码..
    		...........
    	}
    	......
    }
    

    首先执行登录之前的操作,然后,关键是$this->switchIdentity($identity, $duration)这个方法:

    public function switchIdentity($identity, $duration = 0)
    {
    	......
        ......
    	if ($identity) {
    		......
    		......
    		if ($duration > 0 && $this->enableAutoLogin) {
    			$this->sendIdentityCookie($identity, $duration);
    		}
    	} elseif ($this->enableAutoLogin) {
    		......
    	}
    }
    

    在$this->sendIdentityCookie($identity, $duration);这里把cookie设置进去

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

    Yii::$app->getResponse()->getCookies()->add($cookie); 这里设置cookie

    到这里,应该解决了cookie的设置的问题了吧。

    然后说说自动登录的实现
    在SiteController中的actionLogin()方法,他判断这个用户是不是登录用户,如果不是,则返回主页或者说登录页

    if (!\Yii::$app->user->isGuest) {
                return $this->goHome();
    }
    

    还是走到\yii\web\User这个类,调用了getIsGuest()方法,getIsGuest()方法调用getIdentity($autoRenew = true)方法

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

    是否开启自动登录($this->enableSession && $autoRenew),是,那么执行renewAuthStatus()方法:

    protected function renewAuthStatus()
    {
    	......
    	...前面代码是session有值的判断,不看他...
    	......
    
    	if ($this->enableAutoLogin) {
    		if ($this->getIsGuest()) {
    			$this->loginByCookie();
    		} elseif ($this->autoRenewCookie) {
    			$this->renewIdentityCookie();
    		}
    	}
    }
    

    启用自动登录$this->enableAutoLogin为true,然后判断是否是访客$this->getIsGuest(),如果是,则执行登录,从cookie登录$this->loginByCookie();这就是cookie登录的具体实现

    protected function loginByCookie()
        {
    		//cookie取值
            $value = Yii::$app->getRequest()->getCookies()->getValue($this->identityCookie['name']);
            if ($value === null) {
                return;
            }
    
            $data = json_decode($value, true);
            if (count($data) !== 3 || !isset($data[0], $data[1], $data[2])) {
                return;
            }
    
            list ($id, $authKey, $duration) = $data;
            /* @var $class IdentityInterface */
            $class = $this->identityClass;
            $identity = $class::findIdentity($id);
            if ($identity === null) {
                return;
            } elseif (!$identity instanceof IdentityInterface) {
                throw new InvalidValueException("$class::findIdentity() must return an object implementing IdentityInterface.");
            }
    
            if ($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);
                }
            } else {
                Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
            }
        }
    

    $identity = $class::findIdentity($id);//根据cookie保存的记录id在数据库中找,这里调用的是在配置文件中main.php配置的

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

    common\models\User这个类的findIdentity($id)方法

    public static function findIdentity($id)
        {
            return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
        }
    

    if ($identity->validateAuthKey($authKey)) {} 则调用 common\models\User这个类的validateAuthKey($authKey)方法,实际上就是判断这个记录id的auth_key这个数据库的值是否跟保存到cookie中的一样,如果一样,返回true。
    目的是,所以,如果管理员要修改一个帐号的密码,实际上出了修改他的密码password_hash之外,还需要修改auth_key,否则他如果以前登录过。cookie有值,一样可以正常登录。这点很重要

    然后就没啥好说的拉,就是正常的登录流程拉,个人建议,好好利用ide的debug功能,跟踪代码绝对杠杠的

    我大概明白了,我再测试几次应该就能弄明白,现在就是自动验证登录这地方不知道怎么做呢

  • 回复了 的回答

    完整的具体实现在高级版脚手架那块。
    按照你所理解的登录,是两种。token是验证 API 授权才需要用到的。
    你可以参考这个连接http://www.yiichina.com/tutorial/965,它拥有无比完整的代码。然后把登录流程看一遍(在vendor目录下的代码可以不用看),再结合权威指南的安全-》认证那块。你上述的所有问题必定都可以在这两块得到解决。

    用户第一次登陆,然后把浏览器关掉,然后再打开浏览器,进入我的网站,登陆状态直接就应该是登录的吧?那是每次都要验证一次吗?还是?

  • 回复了 的回答

    完整的具体实现在高级版脚手架那块。
    按照你所理解的登录,是两种。token是验证 API 授权才需要用到的。
    你可以参考这个连接http://www.yiichina.com/tutorial/965,它拥有无比完整的代码。然后把登录流程看一遍(在vendor目录下的代码可以不用看),再结合权威指南的安全-》认证那块。你上述的所有问题必定都可以在这两块得到解决。

    正常登录OK,COOKIE自动登录就很麻烦,一,用户登录过一次,而且点过“记住我”,这时候cookie里保存的是什么?如果这个cookie被别人知道了,别人能用这个cookie来登录吗,如果用户在别的地方登录,那是不是要更新数据库里的authkey字段的值,让之前的cookie失效,如果我自己做这些我也都能做出来,但是YII2自己有,我就想知道如何根据YII2自带的登录机制去完成这些。

  • 回复了 的回答

    先说自动登录,cookie在哪里设置的,允许自动登录必须得启用enableAutoLogin,设置为true

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

    然后看登录,在你的LoginFrom中的login方法有这么一行代码:

    return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    

    也是真正执行登录操作的代码,他实际上调用的是\yii\web\User的login方法,这个类的实际路径在:盘符/项目名/vendor/yiisoft/yii2/web/User.php

    public function login(IdentityInterface $identity, $duration = 0)
    {
    	if ($this->beforeLogin($identity, false, $duration)) {
    		$this->switchIdentity($identity, $duration);
                    ............
    		...其他代码..
    		...........
    	}
    	......
    }
    

    首先执行登录之前的操作,然后,关键是$this->switchIdentity($identity, $duration)这个方法:

    public function switchIdentity($identity, $duration = 0)
    {
    	......
        ......
    	if ($identity) {
    		......
    		......
    		if ($duration > 0 && $this->enableAutoLogin) {
    			$this->sendIdentityCookie($identity, $duration);
    		}
    	} elseif ($this->enableAutoLogin) {
    		......
    	}
    }
    

    在$this->sendIdentityCookie($identity, $duration);这里把cookie设置进去

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

    Yii::$app->getResponse()->getCookies()->add($cookie); 这里设置cookie

    到这里,应该解决了cookie的设置的问题了吧。

    然后说说自动登录的实现
    在SiteController中的actionLogin()方法,他判断这个用户是不是登录用户,如果不是,则返回主页或者说登录页

    if (!\Yii::$app->user->isGuest) {
                return $this->goHome();
    }
    

    还是走到\yii\web\User这个类,调用了getIsGuest()方法,getIsGuest()方法调用getIdentity($autoRenew = true)方法

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

    是否开启自动登录($this->enableSession && $autoRenew),是,那么执行renewAuthStatus()方法:

    protected function renewAuthStatus()
    {
    	......
    	...前面代码是session有值的判断,不看他...
    	......
    
    	if ($this->enableAutoLogin) {
    		if ($this->getIsGuest()) {
    			$this->loginByCookie();
    		} elseif ($this->autoRenewCookie) {
    			$this->renewIdentityCookie();
    		}
    	}
    }
    

    启用自动登录$this->enableAutoLogin为true,然后判断是否是访客$this->getIsGuest(),如果是,则执行登录,从cookie登录$this->loginByCookie();这就是cookie登录的具体实现

    protected function loginByCookie()
        {
    		//cookie取值
            $value = Yii::$app->getRequest()->getCookies()->getValue($this->identityCookie['name']);
            if ($value === null) {
                return;
            }
    
            $data = json_decode($value, true);
            if (count($data) !== 3 || !isset($data[0], $data[1], $data[2])) {
                return;
            }
    
            list ($id, $authKey, $duration) = $data;
            /* @var $class IdentityInterface */
            $class = $this->identityClass;
            $identity = $class::findIdentity($id);
            if ($identity === null) {
                return;
            } elseif (!$identity instanceof IdentityInterface) {
                throw new InvalidValueException("$class::findIdentity() must return an object implementing IdentityInterface.");
            }
    
            if ($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);
                }
            } else {
                Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__);
            }
        }
    

    $identity = $class::findIdentity($id);//根据cookie保存的记录id在数据库中找,这里调用的是在配置文件中main.php配置的

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

    common\models\User这个类的findIdentity($id)方法

    public static function findIdentity($id)
        {
            return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
        }
    

    if ($identity->validateAuthKey($authKey)) {} 则调用 common\models\User这个类的validateAuthKey($authKey)方法,实际上就是判断这个记录id的auth_key这个数据库的值是否跟保存到cookie中的一样,如果一样,返回true。
    目的是,所以,如果管理员要修改一个帐号的密码,实际上出了修改他的密码password_hash之外,还需要修改auth_key,否则他如果以前登录过。cookie有值,一样可以正常登录。这点很重要

    然后就没啥好说的拉,就是正常的登录流程拉,个人建议,好好利用ide的debug功能,跟踪代码绝对杠杠的

    也就是说authkey不是用来判断登录的,而是判断密码是否修改的意思?

总监 等级规则
2135/5000
资料完整度
60/100
用户活跃度
0/100

Ta的关注

3

Ta的粉丝

10

Ta的访客

82