Yii的用户认证分为两个部分,一个是User组件,负责管理用户认证状态的,包括登录,登出,检测当前登录状态等,源文件位于vender/yiisoft/yii2/web/User.php。另一个是实现接口IdentityInterface的模型,同时必须继承ActiveRecord,当用户登录注册时,组件User会通过模型中的接口方法,对用户进行验证。

  对于用户状态切换主要通过switchIdentity方法实现的,比如注册后,用户登录时,会用到User组件中的switchIdentity方法,如下:

/*** Switches to a new identity for the current user.** When [[enableSession]] is true, this method may use session and/or cookie to store the user identity information,* according to the value of `$duration`. Please refer to [[login()]] for more details.** This method is mainly called by [[login()]], [[logout()]] and [[loginByCookie()]]* when the current user needs to be associated with the corresponding identity information.** @param IdentityInterface|null $identity the identity information to be associated with the current user.* If null, it means switching the current user to be a guest.* @param integer $duration number of seconds that the user can remain in logged-in status.* This parameter is used only when `$identity` is not null.*/public function switchIdentity($identity, $duration = 0){$this->setIdentity($identity);if (!$this->enableSession) {return;}/* Ensure any existing identity cookies are removed. */if ($this->enableAutoLogin) {$this->removeIdentityCookie();}$session = Yii::$app->getSession();if (!YII_ENV_TEST) {$session->regenerateID(true);}$session->remove($this->idParam);$session->remove($this->authTimeoutParam);if ($identity) {$session->set($this->idParam, $identity->getId());if ($this->authTimeout !== null) {$session->set($this->authTimeoutParam, time() + $this->authTimeout);}if ($this->absoluteAuthTimeout !== null) {$session->set($this->absoluteAuthTimeoutParam, time() + $this->absoluteAuthTimeout);}if ($duration > 0 && $this->enableAutoLogin) {$this->sendIdentityCookie($identity, $duration);}}}

  如果写入identity为null,则将用户状态设置为离线,如果不是null,而是模型实例,该方法会将用户模型的id值写入session中,用户打开新页面时,只需下面的方法就可以判断是否已经登录。

//已登录返回true
Yii::$app->user->isGuest

  访问user组件的isGuest属性,会通过魔术方法,调用User组件中的getIsGuest方法

    /*** Returns a value indicating whether the user is a guest (not authenticated).* @return boolean whether the current user is a guest.* @see getIdentity()*/public function getIsGuest(){return $this->getIdentity() === null;}

  方法又调用getIdentity()方法

    /*** Returns the identity object associated with the currently logged-in user.* When [[enableSession]] is true, this method may attempt to read the user's authentication data* stored in session and reconstruct the corresponding identity object, if it has not done so before.* @param boolean $autoRenew whether to automatically renew authentication status if it has not been done so before.* This is only useful when [[enableSession]] is true.* @return IdentityInterface|null the identity object associated with the currently logged-in user.* `null` is returned if the user is not logged in (not authenticated).* @see login()* @see logout()*/public function getIdentity($autoRenew = true){if ($this->_identity === false) {if ($this->enableSession && $autoRenew) {$this->_identity = null;$this->renewAuthStatus();} else {return null;}}return $this->_identity;}

  当session启用时,通过renewAuthStatus()更新新用户状态

    /*** Updates the authentication status using the information from session and cookie.** This method will try to determine the user identity using the [[idParam]] session variable.** If [[authTimeout]] is set, this method will refresh the timer.** If the user identity cannot be determined by session, this method will try to [[loginByCookie()|login by cookie]]* if [[enableAutoLogin]] is true.*/protected function renewAuthStatus(){$session = Yii::$app->getSession();$id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null;if ($id === null) {$identity = null;} else {/* @var $class IdentityInterface */$class = $this->identityClass;$identity = $class::findIdentity($id);}$this->setIdentity($identity);if ($identity !== null && ($this->authTimeout !== null || $this->absoluteAuthTimeout !== null)) {$expire = $this->authTimeout !== null ? $session->get($this->authTimeoutParam) : null;$expireAbsolute = $this->absoluteAuthTimeout !== null ? $session->get($this->absoluteAuthTimeoutParam) : null;if ($expire !== null && $expire < time() || $expireAbsolute !== null && $expireAbsolute < time()) {$this->logout(false);} elseif ($this->authTimeout !== null) {$session->set($this->authTimeoutParam, time() + $this->authTimeout);}}if ($this->enableAutoLogin) {if ($this->getIsGuest()) {$this->loginByCookie();} elseif ($this->autoRenewCookie) {$this->renewIdentityCookie();}}}

  该方法主要通过session取出用户id,然后通过id获取用户模型实例,然后使用实例进行登录,和更新认证过期时间。

  下面实现一个常用的用户注册登录功能模块,用户只有登录后才可以进入home页面

  User模型:

<?php
/*** Created by PhpStorm.* User: zhenbao* Date: 16/10/17* Time: 下午4:14*/namespace app\models;use Yii;
use yii\web\IdentityInterface;
use yii\db\ActiveRecord;class User extends ActiveRecord implements IdentityInterface
{const LOGIN = "login";const REGISTER = "register";public function scenarios(){return [self::LOGIN => ['username', 'password'],self::REGISTER => ['username', 'password']];}public static function tableName(){return "user";}public static function findIdentity($id){return static::findOne($id);}public static function findIdentityByAccessToken($token, $type = null){return static::findOne(['accessToken' => $token]);}public function getId(){return $this -> id;}public function getAuthKey(){return $this -> authKey;}public function validateAuthKey($authKey){return $this -> getAuthKey() === $authKey;}public static function findIdentityByUsername($username){return static::findOne(['username' => $username]);}public function validatePassword($password){return $this -> password === sha1($password);}public function setPassword(){$this -> password = sha1($this -> password);return true;}public function beforeSave($insert){if(parent::beforeSave($insert)){if($this -> isNewRecord){$this -> authKey = Yii::$app -> security -> generateRandomString();}return true;}return false;}
}

  控制器:

<?phpnamespace app\controllers;use Yii;
use yii\web\Controller;
use app\models\User;
use yii\web\Cookie;class UserController extends Controller
{/**默认方法为home方法* @var string*/public $defaultAction = 'home';/**用户登录,当已经登录直接跳转home页面,* 否则,查看是否有访问accessToken,如果有使用accessToken登录,如果accessToken无效则删除accessToken然后返回到登录界面* 如果没有accessToken则使用用户的登录密码登录,验证成功后,查看是否选择了记住我,有则生成accessToken,下次直接使用accessToken登录* 登录失败,返回到登录界面重新登录。* @return string|\yii\web\Response*/public function actionLogin(){$request = Yii::$app->request->post('User');//如果已经登录获取认证identity然后进入home页面if (!(Yii::$app->user->isGuest)) {return $this->redirect('/?r=user/home');} else {//如果没有登录,查看cookie中是否有accessToken,如果有尝试使用accessToken登录,accessToken登录失败,则删除这个无效的accessToken$accessToken = Yii::$app->request->cookies->getValue('accessToken');if ($accessToken !== null) {if (Yii::$app->user->loginByAccessToken($accessToken)) {return $this->redirect("/?r=user/home");} else {Yii::$app->request->cookies->remove("accessToken");$user = new User(['scenario' => 'login']);return $this->renderPartial('login', ['model' => $user]);}}//尝试用户名密码登录,如果验证成功,查看是否有点击记住我,如果有生成accessToken,下次直接accessToken登录$request = Yii::$app->request->post('User');if ($request && isset($request['username']) && isset($request['password'])) {$user = User::findIdentityByUsername($request['username']);if ($user && $user->validatePassword($request['password'])) {$remeberMe = Yii::$app->request->post('remeberMe');if ($remeberMe === 'on') {//生成访问accessToken$user->accessToken = Yii::$app->security->generateRandomString();$user->scenario = 'login';$user->save();Yii::$app->response->cookies->add(new Cookie(['name' => 'accessToken','value' => $user->accessToken,'expire' => time() + 3600 * 24 * 7]));}Yii::$app->user->login($user);return $this->redirect('/?r=user/home');}}//accessToken和账号密码均无法登录,重新返回登录界面$user = new User(['scenario' => 'login']);return $this->renderPartial('login', ['model' => $user]);}}/**根据用户是否登录,选择跳转页面* @return string|\yii\web\Response*/public function actionHome(){if (Yii::$app->user->isGuest) {return $this->redirect('/?r=user/login');}$user = Yii::$app->user->getIdentity();return $this->renderPartial('home', ['user' => $user]);}/**退出登录,如果有删除accessToken,返回登录页面* @return \yii\web\Response*/public function actionLogout(){$user = Yii::$app->user->getIdentity();Yii::$app->user->logout($user);$accessToken = Yii::$app->request->cookies->getValue('accessToken');if ($accessToken !== null) {Yii::$app->response->cookies->remove('accessToken');}return $this->redirect('/?r=user/login');}/*** 注册用户,如果注册成功自动进入home主页,注册失败进入注册页面* @return string|\yii\web\Response*/public function actionRegister(){$user = new User(['scenario' => 'register']);$request = Yii::$app->request->post();if ($request) {if ($user->load($request) && $user->setPassword() && $user->save()) {Yii::$app->user->login($user);return $this->redirect('/?r=user/login');}}return $this->renderPartial('register', ['model' => $user]);}
}

  视图login

<?phpuse yii\helpers\Html;
use yii\bootstrap\ActiveForm;$form = ActiveForm::begin(['id' => 'user','options' => ['class' => 'form-horizontal'],'fieldConfig' => ['template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>",'labelOptions' => ['class' => 'col-lg-1 control-label'],],]); ?><?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<input type="checkbox" name="remeberMe" >记住我
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
<?php ActiveForm::end(); ?>
<a href="/?r=user/register">注册</a>

  视图注册:

<?phpuse yii\helpers\Html;
use yii\bootstrap\ActiveForm;$this->title = 'register';$form = ActiveForm::begin(['id' => 'login-form','options' => ['class' => 'form-horizontal'],'fieldConfig' => ['template' => "{label}\n<div class=\"col-lg-3\">{input}</div>\n<div class=\"col-lg-8\">{error}</div>",'labelOptions' => ['class' => 'col-lg-1 control-label'],],
]); ?><?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= Html::submitButton('Register', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
<?php ActiveForm::end(); ?>
<a href="/?r=user/login">登录</a>

  home视图:

<?phpecho $user -> username;
?>
<a href="/?r=user/logout">退出</a>

  运行:

home页面

文档:http://www.yiichina.com/doc/guide/2.0/security-authentication

转载于:https://www.cnblogs.com/yangxunwu1992/p/5976550.html

Yii2 认证实现原理和示例相关推荐

  1. CPU Cache原理与示例

    CPU Cache原理与示例 基础知识 现在的 CPU 多核技术,都会有几级缓存,老的 CPU 会有两级内存(L1 和 L2),新的CPU会有三级内存(L1,L2,L3 ),如下图所示: 其中:  ...

  2. Swift与LLVM-Clang原理与示例

    Swift与LLVM-Clang原理与示例 LLVM 学习 从 简单汇编基础 到 Swift 不简单的 a + 1 作为iOS开发,程序崩溃犹如家常便饭,秉着没有崩溃也要制造崩溃的原则 每天都吃的很饱 ...

  3. Oracle 并行原理与示例总结

    <Oracle 并行原理与示例总结> 并行:把一个工作分成几份,分给不同进程同时进行处理. 进程层面 并发:多个会话同时进行访问,就是通常所说并发数.会话层面 数据库版本 LEO1@LEO ...

  4. asp.net core 使用identityServer4的密码模式来进行身份认证(2) 认证授权原理

    前言:本文将会结合asp.net core 认证源码来分析起认证的原理与流程.asp.net core版本2.2 对于大部分使用asp.net core开发的人来说. 下面这几行代码应该很熟悉了. s ...

  5. 信安教程第二版-第6章认证技术原理与应用

    第6章 认证技术原理与应用 6.1 认证概述 115 6.1.1 认证概念 115 6.1.2 认证依据 115 6.1.3 认证原理 116 6.1.4 认证发展 117 6.2 认证类型与认证过程 ...

  6. 转载 OAuth认证协议原理分析及使用方法

    本文系转载 原文地址http://kejibo.com/oauth/ 感谢原作者 新:oauth第二代  oauth2开放认证协议原理及案例分析 写于 2011-8-4 twitter或豆瓣用户一定会 ...

  7. 《Arduino开发实战指南:机器人卷》一3.6 编程原理与示例程序

    本节书摘来华章计算机<Arduino开发实战指南:机器人卷>一书中的第3章 ,第3.6节,黄文恺 伍冯洁 陈 虹 编著更多章节内容可以访问云栖社区"华章计算机"公众号查 ...

  8. TensorFlow XLA优化原理与示例

    TensorFlow XLA优化原理与示例 XLA概述 XLA(加速线性代数)是用于优化TensorFlow计算的线性代数的域特定编译器.结果是在服务器和移动平台上的速度,内存使用率和可移植性得到了改 ...

  9. 逆向工程核心原理图书-示例样本(无病毒)

    逆向工程核心原理图书-示例样本(无病毒) https://github.com/snappyJack/reverse-core

最新文章

  1. Linux目录和文件中的常用命令(二)
  2. Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础
  3. C#编程总结(七)数据加密——附源码
  4. 《关键对话》学习总结
  5. java_day19_MVC和配置文件
  6. Android工程中javax annotation Nullable找不到的替代方案
  7. 【每日算法】【图论】【最小边覆盖 最小路径覆盖 最小顶点覆盖 最大独立集 最大团】
  8. 护航Lazada双11购物节 阿里云CDN全球化火力全开
  9. 用了都说好的SCI在线绘图工具来了~~~~~~~
  10. java 析构函数_《JAVA编程思想》5分钟速成:第5章(初始化和清理)
  11. sql between包括两端吗_sql:简单查询
  12. Mongodb的oplogsize修改
  13. latex常用最要快捷键
  14. android 叠加视图 重启,android-后台应用程序以侦听拖动手势
  15. 项目中常用到的正则(价格千位分割格式化,手机号3-4-4格式化,密码验证,去除空格,获取url参数,检测24小时时间制,检测url前缀,检测中文,检测手机号,英文单词前后加空格,判断版本号)
  16. 雷云Razer Synapse2.0使用测评 -第二次作业
  17. python matplotlib pColor 网格线 消除
  18. html中怎样写渐变色代码,如何用CSS写渐变色
  19. 深度丨边缘计算,星火燎原
  20. vpu测试_一种普适的手机平台vpu视频编解码性能检测方法

热门文章

  1. System.Int32是个啥?
  2. CSS中flex和inline-flex的区别
  3. Mr.J--C语言编译错误C2039
  4. css内容渐入效果实现
  5. Apriori算法实现
  6. CF#574E. OpenStreetMap 题解
  7. header.vue 调用变量,别的组件导入引用,组件方法事例实例
  8. [bzoj 1398] Vijos1382寻找主人 Necklace 解题报告(最小表示法)
  9. C# DataTable的Distinct解决方案及表的复制
  10. MySQL_数据库表记录的操作